fnordmetric 0.7.5 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- data/doc/V1.0-ROADMAP +97 -0
- data/doc/full_example.rb +95 -511
- data/doc/legacy_example.rb +640 -0
- data/doc/minimal_example.rb +26 -0
- data/doc/preview3.png +0 -0
- data/fnordmetric.gemspec +3 -2
- data/lib/fnordmetric/acceptors/acceptor.rb +29 -0
- data/lib/fnordmetric/{inbound_stream.rb → acceptors/tcp_acceptor.rb} +8 -5
- data/lib/fnordmetric/{inbound_datagram.rb → acceptors/udp_acceptor.rb} +9 -8
- data/lib/fnordmetric/api.rb +2 -2
- data/lib/fnordmetric/context.rb +37 -18
- data/lib/fnordmetric/defaults.rb +9 -0
- data/lib/fnordmetric/ext.rb +72 -0
- data/lib/fnordmetric/gauge.rb +37 -10
- data/lib/fnordmetric/gauge_calculations.rb +38 -16
- data/lib/fnordmetric/gauge_modifiers.rb +67 -0
- data/lib/fnordmetric/gauge_rendering.rb +40 -0
- data/lib/fnordmetric/gauge_validations.rb +15 -0
- data/lib/fnordmetric/gauges/distribution_gauge.rb +85 -0
- data/lib/fnordmetric/gauges/timeseries_gauge.rb +143 -0
- data/lib/fnordmetric/gauges/toplist_gauge.rb +44 -0
- data/lib/fnordmetric/histogram.rb +57 -0
- data/lib/fnordmetric/logger.rb +42 -36
- data/lib/fnordmetric/namespace.rb +47 -23
- data/lib/fnordmetric/session.rb +6 -6
- data/lib/fnordmetric/standalone.rb +15 -35
- data/lib/fnordmetric/timeseries.rb +79 -0
- data/lib/fnordmetric/toplist.rb +61 -0
- data/lib/fnordmetric/version.rb +1 -1
- data/lib/fnordmetric/web/app.rb +122 -0
- data/lib/fnordmetric/web/app_helpers.rb +42 -0
- data/lib/fnordmetric/{dashboard.rb → web/dashboard.rb} +4 -0
- data/lib/fnordmetric/{event.rb → web/event.rb} +7 -2
- data/lib/fnordmetric/web/reactor.rb +87 -0
- data/lib/fnordmetric/web/web.rb +53 -0
- data/lib/fnordmetric/web/websocket.rb +38 -0
- data/lib/fnordmetric/widgets/bars_widget.rb +44 -0
- data/lib/fnordmetric/{html_widget.rb → widgets/html_widget.rb} +0 -0
- data/lib/fnordmetric/widgets/numbers_widget.rb +56 -0
- data/lib/fnordmetric/{pie_widget.rb → widgets/pie_widget.rb} +0 -0
- data/lib/fnordmetric/widgets/timeseries_widget.rb +55 -0
- data/lib/fnordmetric/widgets/toplist_widget.rb +64 -0
- data/lib/fnordmetric/worker.rb +26 -25
- data/lib/fnordmetric.rb +85 -115
- data/readme.md +362 -0
- data/spec/gauge_like_shared.rb +54 -0
- data/spec/gauge_spec.rb +2 -36
- data/spec/namespace_spec.rb +25 -11
- data/spec/spec_helper.rb +4 -0
- data/spec/{inbound_stream_spec.rb → tcp_acceptor_spec.rb} +3 -3
- data/spec/timeseries_gauge_spec.rb +54 -0
- data/spec/{inbound_datagram_spec.rb → udp_acceptor_spec.rb} +3 -3
- data/web/fnordmetric.css +786 -0
- data/web/haml/app.haml +38 -0
- data/web/haml/distribution_gauge.haml +118 -0
- data/web/haml/timeseries_gauge.haml +80 -0
- data/web/haml/toplist_gauge.haml +194 -0
- data/web/img/head.png +0 -0
- data/web/img/list.png +0 -0
- data/web/img/list_active.png +0 -0
- data/web/img/list_hover.png +0 -0
- data/web/img/loader_white.gif +0 -0
- data/web/img/navbar.png +0 -0
- data/web/img/navbar_btn.png +0 -0
- data/web/img/picto_gauge.png +0 -0
- data/web/js/fnordmetric.bars_widget.js +178 -0
- data/web/js/fnordmetric.dashboard_view.js +99 -0
- data/web/js/fnordmetric.gauge_view.js +260 -0
- data/web/js/fnordmetric.html_widget.js +21 -0
- data/web/js/fnordmetric.js +255 -0
- data/web/js/fnordmetric.numbers_widget.js +121 -0
- data/web/js/fnordmetric.overview_view.js +35 -0
- data/web/js/fnordmetric.pie_widget.js +118 -0
- data/web/js/fnordmetric.realtime_timeline_widget.js +175 -0
- data/web/js/fnordmetric.session_view.js +343 -0
- data/web/js/fnordmetric.timeline_widget.js +333 -0
- data/web/js/fnordmetric.timeseries_widget.js +388 -0
- data/web/js/fnordmetric.toplist_widget.js +112 -0
- data/web/js/fnordmetric.ui.js +91 -0
- data/web/js/fnordmetric.util.js +244 -0
- data/{pub → web}/loader.gif +0 -0
- data/web/vendor/d3.v2.js +9382 -0
- data/web/vendor/font-awesome/css/font-awesome.css +239 -0
- data/web/vendor/font-awesome/font/fontawesome-webfont.eot +0 -0
- data/web/vendor/font-awesome/font/fontawesome-webfont.svg +175 -0
- data/web/vendor/font-awesome/font/fontawesome-webfont.svgz +0 -0
- data/web/vendor/font-awesome/font/fontawesome-webfont.ttf +0 -0
- data/web/vendor/font-awesome/font/fontawesome-webfont.woff +0 -0
- data/web/vendor/jquery-1.6.2.min.js +18 -0
- data/web/vendor/jquery-ui.min.js +413 -0
- data/web/vendor/jquery.maskedinput.js +252 -0
- data/web/vendor/rickshaw.css +286 -0
- data/web/vendor/rickshaw.fnordmetric.js +2676 -0
- metadata +129 -79
- data/Gemfile +0 -6
- data/README.md +0 -404
- data/Rakefile +0 -6
- data/doc/version +0 -1
- data/haml/app.haml +0 -79
- data/haml/widget.haml +0 -9
- data/lib/fnordmetric/app.rb +0 -163
- data/lib/fnordmetric/average_metric.rb +0 -7
- data/lib/fnordmetric/bars_widget.rb +0 -26
- data/lib/fnordmetric/combine_metric.rb +0 -7
- data/lib/fnordmetric/count_metric.rb +0 -13
- data/lib/fnordmetric/funnel_widget.rb +0 -2
- data/lib/fnordmetric/metric.rb +0 -80
- data/lib/fnordmetric/metric_api.rb +0 -37
- data/lib/fnordmetric/numbers_widget.rb +0 -26
- data/lib/fnordmetric/report.rb +0 -29
- data/lib/fnordmetric/sum_metric.rb +0 -13
- data/lib/fnordmetric/timeline_widget.rb +0 -30
- data/lib/fnordmetric/toplist_widget.rb +0 -25
- data/pub/fnordmetric.css +0 -145
- data/pub/fnordmetric.js +0 -1179
- data/pub/vendor/highcharts.js +0 -170
- data/pub/vendor/jquery-1.6.1.min.js +0 -18
@@ -0,0 +1,121 @@
|
|
1
|
+
FnordMetric.widgets.numbersWidget = function(){
|
2
|
+
|
3
|
+
var max_per_row = 8;
|
4
|
+
var opts;
|
5
|
+
|
6
|
+
function render(_opts){
|
7
|
+
|
8
|
+
opts = _opts;
|
9
|
+
|
10
|
+
opts.elem.append(
|
11
|
+
$('<div class="headbar small"></div>').html(opts.title)
|
12
|
+
).css({
|
13
|
+
'marginBottom': 20,
|
14
|
+
'overflow': 'hidden'
|
15
|
+
});
|
16
|
+
|
17
|
+
if(!opts.series_titles){
|
18
|
+
opts.series_titles = {};
|
19
|
+
}
|
20
|
+
|
21
|
+
for(k in opts.series){
|
22
|
+
|
23
|
+
if (!opts.series_titles[opts.series[k]]){
|
24
|
+
opts.series_titles[opts.series[k]] = opts.series[k];
|
25
|
+
}
|
26
|
+
|
27
|
+
var container = $('<div></div>')
|
28
|
+
.addClass('numbers_container')
|
29
|
+
.attr('rel', opts.series[k])
|
30
|
+
.append($('<div class="title">').html(opts.series_titles[opts.series[k]]));
|
31
|
+
|
32
|
+
opts.elem.append(container);
|
33
|
+
}
|
34
|
+
|
35
|
+
if(opts.autoupdate){
|
36
|
+
var secs = parseInt(opts.autoupdate);
|
37
|
+
if(secs > 0){
|
38
|
+
|
39
|
+
var autoupdate_interval = window.setInterval(function(){
|
40
|
+
requestValues();
|
41
|
+
}, secs*1000);
|
42
|
+
|
43
|
+
$('body').bind('fm_dashboard_close', function(){
|
44
|
+
window.clearInterval(autoupdate_interval);
|
45
|
+
});
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
requestValues();
|
50
|
+
}
|
51
|
+
|
52
|
+
function resize(){
|
53
|
+
$('.numbers_container', opts.elem).each(function(i, e){
|
54
|
+
var num_numbers = $('.number', e).length;
|
55
|
+
if(num_numbers > max_per_row){ num_numbers = max_per_row; }
|
56
|
+
$(e).css('width', (num_numbers * 95)+'px');
|
57
|
+
});
|
58
|
+
}
|
59
|
+
|
60
|
+
function requestValues(){
|
61
|
+
for(k in opts.series){
|
62
|
+
FnordMetric.publish({
|
63
|
+
"namespace": FnordMetric.currentNamespace,
|
64
|
+
"type": "widget_request",
|
65
|
+
"klass": "NumbersWidget",
|
66
|
+
"channel": opts.channel,
|
67
|
+
"cmd": "values_for",
|
68
|
+
"gauge": opts.series[k],
|
69
|
+
"offsets": opts.offsets,
|
70
|
+
"widget_key": opts.widget_key
|
71
|
+
})
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
function renderValues(series, values){
|
76
|
+
for(vkey in values){
|
77
|
+
if(!values[vkey].desc){ values[vkey].desc = vkey; }
|
78
|
+
|
79
|
+
var celem = $('.numbers_container[rel="'+series+'"]', opts.elem)
|
80
|
+
var velem = $('.number[rel="'+vkey+'"]', celem);
|
81
|
+
var vdesc = FnordMetric.util.evilFormat(values[vkey].desc);
|
82
|
+
|
83
|
+
if (velem.length == 0){
|
84
|
+
velem = $('<div></div>')
|
85
|
+
.addClass('number')
|
86
|
+
.attr('rel', vkey)
|
87
|
+
.append($('<span class="desc">').html(vdesc))
|
88
|
+
.append($('<span class="value">').html(0))
|
89
|
+
celem.append(velem);
|
90
|
+
}
|
91
|
+
|
92
|
+
if(!!opts.dont_animate){
|
93
|
+
velem.attr('data', values[vkey].value)
|
94
|
+
$('.value', velem).html(FnordMetric.util.formatGaugeValue(vkey, values[vkey].value));
|
95
|
+
} else {
|
96
|
+
velem.attr('data', values[vkey].value)
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
resize();
|
101
|
+
|
102
|
+
if(!opts.dont_animate){
|
103
|
+
FnordMetric.util.updateNumbers($(opts.elem), 4);
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
function announce(ev){
|
108
|
+
if(ev.widget_key == opts.widget_key){
|
109
|
+
if((ev.class == "widget_response") && (ev.cmd == "values_for")){
|
110
|
+
renderValues(ev.series, ev.values)
|
111
|
+
}
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
115
|
+
|
116
|
+
return {
|
117
|
+
render: render,
|
118
|
+
announce: announce
|
119
|
+
};
|
120
|
+
|
121
|
+
};
|
@@ -0,0 +1,35 @@
|
|
1
|
+
FnordMetric.views.overviewView = function(){
|
2
|
+
var widgets = [];
|
3
|
+
var viewport = null;
|
4
|
+
|
5
|
+
function load(_viewport){
|
6
|
+
viewport = _viewport.html('');
|
7
|
+
|
8
|
+
viewport.append('<div class="navbar"></div>');
|
9
|
+
viewport.append('<h1>Application Overview</h1>');
|
10
|
+
viewport.append('<h3>Welcome to FnordMetric :)</h3>');
|
11
|
+
|
12
|
+
// $.ajax({
|
13
|
+
// url: FnordMetric.p + '/' + FnordMetric.currentNamespace+'/dashboard/'+dashboard_name,
|
14
|
+
// success: function(resp, status){
|
15
|
+
// var conf = JSON.parse(resp);
|
16
|
+
// renderWidgets(conf.widgets);
|
17
|
+
// }
|
18
|
+
// });
|
19
|
+
};
|
20
|
+
|
21
|
+
function resize(){
|
22
|
+
// here be dragons
|
23
|
+
}
|
24
|
+
|
25
|
+
function close(){
|
26
|
+
// here be dragons
|
27
|
+
}
|
28
|
+
|
29
|
+
return {
|
30
|
+
load: load,
|
31
|
+
resize: resize,
|
32
|
+
close: close
|
33
|
+
};
|
34
|
+
|
35
|
+
};
|
@@ -0,0 +1,118 @@
|
|
1
|
+
FnordMetric.widgets.pieWidget = function(){
|
2
|
+
|
3
|
+
function render(opts){
|
4
|
+
|
5
|
+
return drawLayout();
|
6
|
+
|
7
|
+
var widget_uid = FnordMetric.util.getNextWidgetUID();
|
8
|
+
var chart=false;
|
9
|
+
|
10
|
+
function redraw(first_time, silent){
|
11
|
+
if(!silent){ $(opts.elem).css('opacity', 0.5); }
|
12
|
+
var gauge_values = {};
|
13
|
+
var gauges_left = opts.gauges.length;
|
14
|
+
var at = parseInt(new Date().getTime()/1000);
|
15
|
+
$(opts.gauges).each(function(i,gauge){
|
16
|
+
$.ajax({
|
17
|
+
url: FnordMetric.p + '/' + FnordMetric.currentNamespace+'/gauge/'+gauge+'?at='+at,
|
18
|
+
success: function(_resp){
|
19
|
+
var resp = JSON.parse(_resp);
|
20
|
+
gauges_left -= 1;
|
21
|
+
for(_tk in resp){
|
22
|
+
gauge_values[gauge] = parseInt(resp[_tk]||0);
|
23
|
+
}
|
24
|
+
if(gauges_left==0){
|
25
|
+
redrawChart(first_time, gauge_values);
|
26
|
+
}
|
27
|
+
}
|
28
|
+
});
|
29
|
+
});
|
30
|
+
}
|
31
|
+
|
32
|
+
function redrawChart(first_time, gauge_values){
|
33
|
+
|
34
|
+
var series_data = [];
|
35
|
+
|
36
|
+
for(_gkey in gauge_values){
|
37
|
+
series_data.push([
|
38
|
+
opts.gauge_titles[_gkey],
|
39
|
+
gauge_values[_gkey]
|
40
|
+
]);
|
41
|
+
}
|
42
|
+
|
43
|
+
/*chart = new Highcharts.Chart({
|
44
|
+
chart: {
|
45
|
+
renderTo: 'container-'+widget_uid,
|
46
|
+
defaultSeriesType: 'pie',
|
47
|
+
height: 270,
|
48
|
+
spacingTop: 5,
|
49
|
+
spacingBottom: 30
|
50
|
+
},
|
51
|
+
credits: {
|
52
|
+
enabled: false
|
53
|
+
},
|
54
|
+
title: { text: '' },
|
55
|
+
legend: {
|
56
|
+
layout: 'horizontal',
|
57
|
+
align: 'top',
|
58
|
+
verticalAlign: 'top',
|
59
|
+
margin: 25,
|
60
|
+
borderWidth: 0
|
61
|
+
},
|
62
|
+
tooltip: {
|
63
|
+
formatter: function() {
|
64
|
+
return '<b>'+ this.point.name +'</b>: '+ this.y + ' (' + this.percentage.toFixed(1) + '%)';
|
65
|
+
}
|
66
|
+
},
|
67
|
+
plotOptions: {
|
68
|
+
pie: {
|
69
|
+
animation: first_time,
|
70
|
+
dataLabels: {
|
71
|
+
formatter: function() {
|
72
|
+
return '<b>'+ this.point.name +'</b><br />'+ this.percentage.toFixed(1) +' %';
|
73
|
+
}
|
74
|
+
}
|
75
|
+
}
|
76
|
+
},
|
77
|
+
series: [
|
78
|
+
{
|
79
|
+
name: opts.title,
|
80
|
+
data: series_data
|
81
|
+
}
|
82
|
+
]
|
83
|
+
});*/
|
84
|
+
|
85
|
+
//chart.redraw();
|
86
|
+
$(opts.elem).css('opacity', 1);
|
87
|
+
}
|
88
|
+
|
89
|
+
function drawLayout(){
|
90
|
+
$(opts.elem).append( $('<div></div>').attr('class', 'headbar small').append(
|
91
|
+
$('<span></span>').html(opts.title)
|
92
|
+
) ).append(
|
93
|
+
$('<div></div>').attr('id', 'container-'+widget_uid).css({
|
94
|
+
height: 270
|
95
|
+
})
|
96
|
+
);
|
97
|
+
}
|
98
|
+
|
99
|
+
drawLayout();
|
100
|
+
redraw(true);
|
101
|
+
|
102
|
+
if(opts.autoupdate){
|
103
|
+
var autoupdate_interval = window.setInterval(function(){
|
104
|
+
redraw(false, true);
|
105
|
+
}, opts.autoupdate*1000);
|
106
|
+
|
107
|
+
$('body').bind('fm_dashboard_close', function(){
|
108
|
+
window.clearInterval(autoupdate_interval);
|
109
|
+
});
|
110
|
+
}
|
111
|
+
|
112
|
+
}
|
113
|
+
|
114
|
+
return {
|
115
|
+
render: render
|
116
|
+
};
|
117
|
+
|
118
|
+
};
|
@@ -0,0 +1,175 @@
|
|
1
|
+
FnordMetric.widgets.realtimeValueWidget = function(){
|
2
|
+
|
3
|
+
var xpadding = 20;
|
4
|
+
var ypadding = 10;
|
5
|
+
var bmargin = 6;
|
6
|
+
var bwidth = 5;
|
7
|
+
var bcolor = '#06C';
|
8
|
+
var zero_height = 5;
|
9
|
+
|
10
|
+
|
11
|
+
var widget_uid = FnordMetric.util.getNextWidgetUID();
|
12
|
+
var width, height, canvas, opts, max;
|
13
|
+
var bars = [];
|
14
|
+
var tick = false;
|
15
|
+
var next_values = [];
|
16
|
+
var next_value_interval = false;
|
17
|
+
|
18
|
+
|
19
|
+
function render(_opts){
|
20
|
+
opts = _opts;
|
21
|
+
|
22
|
+
drawLayout();
|
23
|
+
|
24
|
+
width = opts.elem.width() - (xpadding * 2) - 15 - 250;
|
25
|
+
height = opts.height || 210;
|
26
|
+
//xtick = width / (xticks - 1);
|
27
|
+
|
28
|
+
canvas = d3.select('#container-'+widget_uid)
|
29
|
+
.append("svg:svg")
|
30
|
+
.attr("width", width+(2*xpadding))
|
31
|
+
.attr("height", height);
|
32
|
+
|
33
|
+
canvas.selectAll("*").remove();
|
34
|
+
|
35
|
+
changeTick(opts.ticks[0]);
|
36
|
+
}
|
37
|
+
|
38
|
+
function changeTick(_tick){
|
39
|
+
tick = _tick;
|
40
|
+
canvas.selectAll('.valuebar').remove();
|
41
|
+
next_values = [];
|
42
|
+
max = 1;
|
43
|
+
|
44
|
+
for(var n=parseInt(width / bmargin); n > 0; n--){
|
45
|
+
drawValue(0, n-1);
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
function nextValue(value){
|
50
|
+
if (value > max){
|
51
|
+
var old_max = max;
|
52
|
+
max = value * 1.2;
|
53
|
+
canvas.selectAll('.valuebar').each(function(){
|
54
|
+
var theight = parseInt($(this).attr('height'))*(old_max/max);
|
55
|
+
if(theight < zero_height){ theight = zero_height; }
|
56
|
+
$(this).attr("y", height-(ypadding*2)-theight)
|
57
|
+
$(this).attr("height", theight);
|
58
|
+
});
|
59
|
+
}
|
60
|
+
|
61
|
+
drawValue(value);
|
62
|
+
|
63
|
+
canvas.selectAll('.valuebar').each(function(){
|
64
|
+
var new_x = parseInt($(this).attr('x'))-bmargin;
|
65
|
+
if(new_x < 5){ new_x = 5; }
|
66
|
+
$(this).attr("x", new_x);
|
67
|
+
});
|
68
|
+
|
69
|
+
pruneValues();
|
70
|
+
next_value_interval = false;
|
71
|
+
nextValueAsync();
|
72
|
+
}
|
73
|
+
|
74
|
+
function nextValueAsync(value){
|
75
|
+
if(value != undefined){
|
76
|
+
next_values.unshift(value);
|
77
|
+
$('.big_number .value', opts.elem).html(FnordMetric.util.formatValue(value));
|
78
|
+
}
|
79
|
+
if(next_values.length > 0){
|
80
|
+
if(!next_value_interval){
|
81
|
+
next_value_interval = window.setInterval(function(){
|
82
|
+
var _v = next_values.pop();
|
83
|
+
if(_v != undefined){ nextValue(_v); }
|
84
|
+
}, 20);
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
function pruneValues(){
|
90
|
+
while(bars.length > (width / bmargin)){
|
91
|
+
bars.pop().remove();
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
function drawValue(value, offset){
|
96
|
+
if(!offset){ offset = 0; }
|
97
|
+
if(!value){ value = 0; }
|
98
|
+
|
99
|
+
if(value > 0){
|
100
|
+
var theight = (height-(ypadding*4)) * (value/max);
|
101
|
+
var fillc = bcolor;
|
102
|
+
} else {
|
103
|
+
var theight = zero_height;
|
104
|
+
var fillc = '#ddd';
|
105
|
+
}
|
106
|
+
|
107
|
+
if(theight < zero_height){
|
108
|
+
theight = zero_height;
|
109
|
+
}
|
110
|
+
|
111
|
+
bars.unshift(canvas
|
112
|
+
.append("svg:rect")
|
113
|
+
.attr("class", "valuebar")
|
114
|
+
.attr("x", width+xpadding-(offset*bmargin))
|
115
|
+
.attr("y", height-(ypadding*2)-theight)
|
116
|
+
.attr("fill", fillc)
|
117
|
+
.attr("width", bwidth)
|
118
|
+
.attr("height", theight));
|
119
|
+
|
120
|
+
}
|
121
|
+
|
122
|
+
function announce(evt){
|
123
|
+
if((evt._class == "widget_push") && (evt.cmd == "value")){
|
124
|
+
if(evt.values[tick]){
|
125
|
+
nextValueAsync(parseFloat(evt.values[tick]));
|
126
|
+
} else {
|
127
|
+
nextValueAsync(0);
|
128
|
+
}
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
function drawLayout(){
|
133
|
+
if(!opts.no_headbar){
|
134
|
+
$(opts.elem).append( $('<div></div>').attr('class', 'headbar').append(
|
135
|
+
$('<h2></h2>').html(opts.title)
|
136
|
+
));
|
137
|
+
}
|
138
|
+
|
139
|
+
$(opts.elem).append(
|
140
|
+
$('<div></div>').attr('id', 'container-'+widget_uid).css({
|
141
|
+
height: opts.height + 6,
|
142
|
+
marginBottom: 20,
|
143
|
+
overflow: 'hidden'
|
144
|
+
}).append(
|
145
|
+
$('<div></div>')
|
146
|
+
.addClass('big_number number')
|
147
|
+
.attr('data-current', 0)
|
148
|
+
.attr('data', 0)
|
149
|
+
.append($('<span class="desc">').html(opts.desc))
|
150
|
+
.append($('<span class="value">'))
|
151
|
+
)
|
152
|
+
);
|
153
|
+
|
154
|
+
if(opts.ticks){
|
155
|
+
$('.headbar', opts.elem).append('<div class="tick_btns btn_group" style="margin-right:17px;"></div>');
|
156
|
+
for(__tick in opts.ticks){
|
157
|
+
var _tick = opts.ticks[__tick];
|
158
|
+
$('.tick_btns', opts.elem).append(
|
159
|
+
$('<div></div>').attr('class', 'button tick').append($('<span></span>')
|
160
|
+
.html(FnordMetric.util.formatTimeRange(_tick)))
|
161
|
+
.attr('data-tick', _tick)
|
162
|
+
.click(function(){
|
163
|
+
changeTick($(this).attr('data-tick'));
|
164
|
+
})
|
165
|
+
);
|
166
|
+
}
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
return {
|
171
|
+
render: render,
|
172
|
+
announce: announce
|
173
|
+
}
|
174
|
+
|
175
|
+
};
|