omf_web 0.9.1 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +0 -1
- data/README.md +8 -2
- data/doc/screenshot.png +0 -0
- data/example/{basic → NOT_WORKING/basic}/hello-world-wired.rb +0 -0
- data/example/{basic → NOT_WORKING/basic}/visualisation.yml +0 -0
- data/example/{brooklyn → NOT_WORKING/brooklyn}/brooklynDemo.sq3 +0 -0
- data/example/{brooklyn → NOT_WORKING/brooklyn}/brooklyn_gps.dat +0 -0
- data/example/{brooklyn → NOT_WORKING/brooklyn}/brooklyn_server.rb +0 -0
- data/example/{brooklyn → NOT_WORKING/brooklyn}/brooklyn_wimax.dat +0 -0
- data/example/{brooklyn → NOT_WORKING/brooklyn}/sql_source.rb +0 -0
- data/example/{code → NOT_WORKING/code}/code_server.rb +0 -0
- data/example/{frisbee → NOT_WORKING/frisbee}/data_sources/parse_log.rb +0 -0
- data/example/{frisbee → NOT_WORKING/frisbee}/data_sources/pxe_slice-2012-06-02t02.25.00-04.00.log +0 -0
- data/example/{frisbee → NOT_WORKING/frisbee}/progress_chart.yaml +0 -0
- data/example/{frisbee → NOT_WORKING/frisbee}/progress_tab.yaml +0 -0
- data/example/{frisbee → NOT_WORKING/frisbee}/progress_table.yaml +0 -0
- data/example/{frisbee → NOT_WORKING/frisbee}/viz_server.rb +0 -0
- data/example/{gec12 → NOT_WORKING/gec12}/gec12-53.rb +0 -0
- data/example/{gec12 → NOT_WORKING/gec12}/gec12_demo.sq3 +0 -0
- data/example/{gec12 → NOT_WORKING/gec12}/gec12_demo_server.rb +0 -0
- data/example/{gec12 → NOT_WORKING/gec12}/visualization.rb +0 -0
- data/example/{incoming → NOT_WORKING/incoming}/ofpu_barchart_widget.yaml +0 -0
- data/example/{log → NOT_WORKING/log}/log_config.xml +0 -0
- data/example/{log → NOT_WORKING/log}/log_server.rb +0 -0
- data/example/{network → NOT_WORKING/network}/flow_tab.yaml +0 -0
- data/example/{network → NOT_WORKING/network}/network_server.rb +0 -0
- data/example/{text → NOT_WORKING/text}/test.md +0 -0
- data/example/{text → NOT_WORKING/text}/test.rb +0 -0
- data/example/{wimax → NOT_WORKING/wimax}/downlink.yaml +0 -0
- data/example/{wimax → NOT_WORKING/wimax}/power.yaml +0 -0
- data/example/{wimax → NOT_WORKING/wimax}/snapshot.db +0 -0
- data/example/{wimax → NOT_WORKING/wimax}/snapshot.sql +0 -0
- data/example/{wimax → NOT_WORKING/wimax}/test.rb +0 -0
- data/example/{wimax → NOT_WORKING/wimax}/uplink.yaml +0 -0
- data/example/{wimax → NOT_WORKING/wimax}/viz_server.rb +0 -0
- data/example/demo/data_sources/mobile_network.rb +3 -0
- data/example/demo/data_sources/static_network.rb +54 -0
- data/example/demo/widgets/charts_tab.yaml +21 -16
- data/example/demo/widgets/linked_graphs_tab.yaml +95 -0
- data/example/demo/widgets/mobile_network_widget.yaml +1 -1
- data/example/demo/widgets/pie_chart_widget.yaml +1 -1
- data/lib/omf-web/config.ru +2 -2
- data/lib/omf-web/data_source_proxy.rb +81 -19
- data/lib/omf-web/rack/websocket_handler.rb +77 -23
- data/lib/omf-web/theme/abstract_page.rb +43 -26
- data/lib/omf-web/theme/bright/code_renderer.rb +1 -1
- data/lib/omf-web/theme/bright/page.rb +1 -0
- data/lib/omf-web/theme/bright/tabbed_renderer.rb +7 -0
- data/lib/omf-web/version.rb +7 -0
- data/lib/omf-web/widget/data_widget.rb +38 -46
- data/lib/omf-web/widget/layout/stacked_layout.rb +2 -1
- data/lib/omf-web/widget/layout/tabbed_layout.rb +1 -2
- data/{MARUKU-LICENSE → lib/omf-web/widget/text/maruku/MARUKU-LICENSE} +0 -0
- data/lib/{maruku → omf-web/widget/text/maruku}/helpers.rb +0 -0
- data/lib/{maruku → omf-web/widget/text/maruku}/input/parse_block.rb +0 -0
- data/lib/{maruku → omf-web/widget/text/maruku}/output/to_html.rb +26 -21
- data/lib/omf-web/widget/text/maruku.rb +5 -0
- data/omf_web.gemspec +2 -1
- data/share/htdocs/{js → UNUSED}/log/table.js +0 -0
- data/share/htdocs/{css → graph/css}/graph.css +0 -0
- data/share/htdocs/{image/graph → graph/img}/bar_chart.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/donut_chart.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/funnel.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/info.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/line_chart.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/line_chart_fill.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/misc.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/overview.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/pie_chart.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/scatter_plot.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/stacked_bar_chart.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/stacked_line_chart.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/table.png +0 -0
- data/share/htdocs/{js/graph → graph/js}/abstract_chart.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/abstract_nv_chart.js +8 -13
- data/share/htdocs/{js/graph → graph/js}/abstract_widget.js +9 -16
- data/share/htdocs/{js/graph → graph/js}/axis.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/barchart.js +2 -2
- data/share/htdocs/{js/graph → graph/js}/code_mirror.js +1 -5
- data/share/htdocs/{js/graph → graph/js}/discrete_bar_chart.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/histogram2.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/holt_winters_chart.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/line_chart3.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/line_chart_with_focus.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/map2.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/multi_barchart.js +1 -1
- data/share/htdocs/graph/js/network2.js +412 -0
- data/share/htdocs/{js/graph → graph/js}/pie_chart2.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/scatter_plot.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/table2.js +17 -20
- data/share/htdocs/js/data_source2.js +187 -60
- data/share/htdocs/js/require3.js +38 -57
- data/share/htdocs/theme/bright/css/bright.css +4 -4
- data/share/htdocs/vendor/jquery/jquery.js +9404 -0
- data/share/htdocs/vendor/osa/LICENSE.txt +11 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_arrow_green_left.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_arrow_yellow_right.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_awareness.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_camera-web.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_cloud.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_contract.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_database.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_desktop.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_desktop_imac.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-music.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-scanner.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-usb-wifi.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-usb.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-wireless-router.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_disposal.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_drive-harddisk.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_drive-optical.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_firewall.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_home.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_hub.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_iPhone.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_ics_drive.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_ics_plc.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_ics_thermometer.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_id_card.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_image-generic.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_laptop.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_lifecycle.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_lightning.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_media-flash.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_media-optical.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_media-tape.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_mobile_pda.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_padlock.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_printer.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_application.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_database.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_directory.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_distribution.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_file.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_gateway.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_identity.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_mail.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_media.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_monitor.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_proxy.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_terminal.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_web.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_site-branch.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_site-factory.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_site-head-office.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_site-neighbourhood.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_audit.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_black_hat.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue_security_specialist.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue_sysadmin.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue_tester.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue_tie.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_architect.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_business_manager.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_developer.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_operations.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_project_manager.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_service_manager.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_warning.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_large_group.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_users_blue_green.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_vpn.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_warning.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_wireless_network.svg +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/.DS_Store +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/add_icon.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/alertbad_icon.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/alertgood_icon.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/back_disabled.jpg +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/back_disabled.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/back_enabled.jpg +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/back_enabled.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/back_enabled_hover.jpg +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/back_enabled_hover.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/bottom-bg.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/forward_disabled.jpg +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/forward_disabled.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/forward_enabled.jpg +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/forward_enabled.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/forward_enabled_hover.jpg +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/forward_enabled_hover.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/icon-remove.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/indicator.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/laptop.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/logo-bottom.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/nav-tab-arrow.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/norbit_big.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/norbit_clipart.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/progress_bar.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/right-bg.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/sort_asc.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/sort_asc_disabled.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/sort_both.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/sort_desc.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/sort_desc_disabled.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/spinner.gif +0 -0
- data/share/htdocs/{svg → vendor/unknown/svg}/ap.svg +0 -0
- data/share/htdocs/{svg → vendor/unknown/svg}/router.svg +0 -0
- metadata +198 -216
- data/example/demo/widgets/dashboard_tab.yaml +0 -28
- data/example/demo/widgets/download_tab.yaml +0 -42
- data/example/demo/widgets/edit_tab.yaml +0 -20
- data/example/demo/widgets/generator_tab.yaml +0 -12
- data/lib/omf-oml/endpoint.rb +0 -175
- data/lib/omf-oml/indexed_table.rb +0 -57
- data/lib/omf-oml/network.rb +0 -413
- data/lib/omf-oml/oml_tuple.rb +0 -62
- data/lib/omf-oml/schema.rb +0 -191
- data/lib/omf-oml/sequel/sequel_server.rb +0 -412
- data/lib/omf-oml/sql_row.rb +0 -302
- data/lib/omf-oml/sql_source.rb +0 -131
- data/lib/omf-oml/table.rb +0 -131
- data/lib/omf-oml/tuple.rb +0 -97
- data/lib/omf_oml.rb +0 -4
- data/share/htdocs/css/coderay.css +0 -127
- data/share/htdocs/css/ie.css +0 -40
- data/share/htdocs/css/lightbox.css +0 -62
- data/share/htdocs/css/scaffold.css +0 -74
- data/share/htdocs/css/screen.css +0 -1313
- data/share/htdocs/css/search.css +0 -102
- data/share/htdocs/css/table.css +0 -538
- data/share/htdocs/css/table2.css +0 -191
- data/share/htdocs/css/welcome.css +0 -103
- data/share/htdocs/css/wfob.css +0 -171
- data/share/htdocs/css/wshow.css +0 -69
- data/share/htdocs/gec9_demo.html +0 -39
- data/share/htdocs/images +0 -1
- data/share/htdocs/js/graph/histogram.js +0 -229
- data/share/htdocs/js/graph/line_chart.js +0 -342
- data/share/htdocs/js/graph/line_chart2.js +0 -232
- data/share/htdocs/js/graph/line_chart_fc.js +0 -94
- data/share/htdocs/js/graph/map.js +0 -85
- data/share/htdocs/js/graph/network.js +0 -591
- data/share/htdocs/js/graph/network2.js +0 -318
- data/share/htdocs/js/graph/pie_chart.js +0 -130
- data/share/htdocs/js/graph/table.js +0 -94
- data/share/htdocs/js/require2.js +0 -1998
- data/share/htdocs/js/timelines.js +0 -101
- data/share/htdocs/stylesheet/grid.css +0 -31
@@ -1,229 +0,0 @@
|
|
1
|
-
|
2
|
-
L.provide('OML.histogram', ["graph/abstract_chart", "#OML.abstract_chart", "graph/axis", "#OML.axis",
|
3
|
-
// ["/resource/vendor/d3/d3.js", "/resource/vendor/d3/d3.layout.js"]],
|
4
|
-
["/resource/vendor/d3/d3.js"]],
|
5
|
-
function () {
|
6
|
-
|
7
|
-
OML['histogram'] = OML.abstract_chart.extend({
|
8
|
-
decl_properties: [
|
9
|
-
['value', 'float', {property: 'value'}],
|
10
|
-
// ['x_axis', 'key', {property: 'x'}],
|
11
|
-
// ['y_axis', 'key', {property: 'y'}],
|
12
|
-
// ['group_by', 'key', {property: 'id', optional: true}],
|
13
|
-
['stroke_width', 'int', 2],
|
14
|
-
['stroke_color', 'color', 'white'],
|
15
|
-
['fill_color', 'color', 'blue']
|
16
|
-
],
|
17
|
-
|
18
|
-
defaults: function() {
|
19
|
-
//var d = OML.histogram.__super__.defaults.call(this);
|
20
|
-
return this.deep_defaults({
|
21
|
-
//bins: 5, // specify the number of bins to be used in the histogram
|
22
|
-
unique: false, // If true, buckets are defined by unique 'values'
|
23
|
-
axis: {
|
24
|
-
x: {
|
25
|
-
ticks: {
|
26
|
-
format: ",.2f"
|
27
|
-
}
|
28
|
-
}
|
29
|
-
}
|
30
|
-
}, OML.histogram.__super__.defaults.call(this));
|
31
|
-
},
|
32
|
-
|
33
|
-
base_css_class: 'oml-line-chart',
|
34
|
-
|
35
|
-
// initialize: function(opts) {
|
36
|
-
// var o = OML.histogram.__super__.defaults.call(this);
|
37
|
-
// OML.histogram.__super__.initialize.call(this, opts);
|
38
|
-
// },
|
39
|
-
|
40
|
-
configure_base_layer: function(vis) {
|
41
|
-
var base = this.base_layer = vis.append("svg:g")
|
42
|
-
.attr("class", "histogram")
|
43
|
-
;
|
44
|
-
//.attr("transform", "translate(0, " + this.h + ")");
|
45
|
-
|
46
|
-
var ca = this.chart_area;
|
47
|
-
this.legend_layer = base.append("svg:g");
|
48
|
-
this.chart_layer = base.append("svg:g");
|
49
|
-
this.axis_layer = base.append('g');
|
50
|
-
},
|
51
|
-
|
52
|
-
redraw: function(data) {
|
53
|
-
var self = this;
|
54
|
-
var o = this.opts;
|
55
|
-
var ca = this.widget_area;
|
56
|
-
var m = this.mapping;
|
57
|
-
|
58
|
-
var hdata;
|
59
|
-
// if (o.unique) {
|
60
|
-
// hdata = this.unique_histogram(data);
|
61
|
-
// } else {
|
62
|
-
var histogram = d3.layout.histogram();
|
63
|
-
histogram.value(m.value);
|
64
|
-
var bins = o.bins ? histogram.bins(o.bins) : histogram.bins();
|
65
|
-
if (o.density != 'undefined"') histogram.frequency(! o.density);
|
66
|
-
hdata = histogram(data);
|
67
|
-
// }
|
68
|
-
|
69
|
-
var u = _.map(_.uniq(data, false, m.value), m.value).sort();
|
70
|
-
|
71
|
-
var x = d3.scale.ordinal()
|
72
|
-
.domain(hdata.map(function(d) {
|
73
|
-
return d.x;
|
74
|
-
}))
|
75
|
-
.rangeRoundBands([0, ca.w]);
|
76
|
-
|
77
|
-
var y = d3.scale.linear()
|
78
|
-
.domain([0, d3.max(hdata.map(function(d) { return d.y; }))])
|
79
|
-
.range([0, ca.h])
|
80
|
-
.nice()
|
81
|
-
;
|
82
|
-
|
83
|
-
this.chart_layer.selectAll("rect")
|
84
|
-
.data(hdata)
|
85
|
-
.enter().append("rect")
|
86
|
-
.attr("width", x.rangeBand())
|
87
|
-
.attr("x", function(d) { return x(d.x) + ca.x; })
|
88
|
-
.attr("y", function(d) { return ca.ty + ca.h - y(d.y); })
|
89
|
-
.attr("height", function(d) { return y(d.y); })
|
90
|
-
.attr("stroke-width", m.stroke_width)
|
91
|
-
.attr("stroke", m.stroke_color)
|
92
|
-
.attr("fill", m.fill_color)
|
93
|
-
;
|
94
|
-
|
95
|
-
var oAxis = o.axis || {};
|
96
|
-
|
97
|
-
// Create an X axis with ticks at the boundaries of the bar charts
|
98
|
-
//
|
99
|
-
var ticks = hdata.map(function(d) { return d.x - 0.5 * d.dx; });
|
100
|
-
var xmin = ticks[0];
|
101
|
-
var xmax = d3.max(hdata.map(function(d) { return d.x + 0.5 * d.dx; }));
|
102
|
-
ticks.push(xmax);
|
103
|
-
var ax_f = d3.scale.linear()
|
104
|
-
.domain([xmin, xmax])
|
105
|
-
.range([0, ca.w])
|
106
|
-
;
|
107
|
-
if (this.xAxis) {
|
108
|
-
var xAxis = this.xAxis.scale(ax_f).tick_values(ticks);
|
109
|
-
this.axis_layer.select('g.x.axis').call(xAxis);
|
110
|
-
} else {
|
111
|
-
var xAxis = this.xAxis = OML.line_chart2_axis(oAxis.x).scale(ax_f).tick_values(ticks).orient("bottom").range([0, ca.w]);
|
112
|
-
this.axis_layer
|
113
|
-
.append('g')
|
114
|
-
.attr("transform", "translate(" + ca.x + "," + (ca.ty + ca.h) + ")")
|
115
|
-
.attr('class', 'x axis')
|
116
|
-
.call(xAxis)
|
117
|
-
;
|
118
|
-
}
|
119
|
-
|
120
|
-
// Y axis is normal
|
121
|
-
//
|
122
|
-
var inv_y = y.range([ca.h, 0]);
|
123
|
-
if (this.yAxis) {
|
124
|
-
var yAxis = this.yAxis.scale(inv_y);
|
125
|
-
this.axis_layer.select('g.y.axis').call(yAxis);
|
126
|
-
} else {
|
127
|
-
var yAxis = this.yAxis = OML.line_chart2_axis(oAxis.y).scale(inv_y).orient("left").range([0, ca.h]);
|
128
|
-
this.axis_layer
|
129
|
-
.append('g')
|
130
|
-
.attr("transform", "translate(" + ca.x + "," + ca.ty + ")")
|
131
|
-
.attr('class', 'y axis')
|
132
|
-
.call(yAxis)
|
133
|
-
;
|
134
|
-
}
|
135
|
-
|
136
|
-
|
137
|
-
},
|
138
|
-
|
139
|
-
// Calculate the 'histogram' over 'data' assuming that applying the 'value' operator
|
140
|
-
// over 'data' provides a limited number of unique values which are treated as the bins.
|
141
|
-
//
|
142
|
-
unique_histogram: function(data) {
|
143
|
-
var self = this;
|
144
|
-
var o = this.opts;
|
145
|
-
var ca = this.widget_area;
|
146
|
-
var value_f = this.mapping.value;
|
147
|
-
|
148
|
-
var h = {};
|
149
|
-
var count = 0;
|
150
|
-
_.map(data, function(s) {
|
151
|
-
var key = value_f(s);
|
152
|
-
count = count + 1;
|
153
|
-
h[key] = 1 + (h[key] || 0);
|
154
|
-
})
|
155
|
-
var buckets = _.keys(h).sort();
|
156
|
-
var result = _.map(buckets, function(k) { return h[k]; });
|
157
|
-
var i = 0;
|
158
|
-
},
|
159
|
-
|
160
|
-
// redraw2: function(data) {
|
161
|
-
// var self = this;
|
162
|
-
// var o = this.opts;
|
163
|
-
// var ca = this.widget_area;
|
164
|
-
// var m = this.mapping;
|
165
|
-
//
|
166
|
-
// /* 'data' should be an an array (each line) of arrays (each tuple)
|
167
|
-
// * The following code assumes that the tuples are sorted in ascending
|
168
|
-
// * value associated with the x-axis.
|
169
|
-
// */
|
170
|
-
// // var x_index = m.x_axis;
|
171
|
-
// // var y_index = m.y_axis;
|
172
|
-
// // var group_by = m.group_by;
|
173
|
-
// // if (group_by != null) {
|
174
|
-
// // data = this.group_by(data, group_by);
|
175
|
-
// // } else {
|
176
|
-
// // data = [data];
|
177
|
-
// // }
|
178
|
-
//
|
179
|
-
// var histogram = d3.layout.histogram();
|
180
|
-
// var x = d3.scale.ordinal();
|
181
|
-
// var y = d3.scale.linear();
|
182
|
-
// //xAxis = d3.svg.axis().scale(x).orient("bottom").tickSize(6, 0);
|
183
|
-
//
|
184
|
-
// histogram.value(m.value);
|
185
|
-
// data = histogram(data);
|
186
|
-
//
|
187
|
-
// // Update the x-scale.
|
188
|
-
// x.domain(data.map(function(d) { return d.x; }))
|
189
|
-
// .rangeRoundBands([0, ca.w], .1);
|
190
|
-
//
|
191
|
-
// // Update the y-scale.
|
192
|
-
// y.domain([0, d3.max(data, function(d) { return d.y; })])
|
193
|
-
// .range([ca.h, 0]);
|
194
|
-
//
|
195
|
-
// // Select the svg element, if it exists.
|
196
|
-
// var svg = this.chart_layer.selectAll(".chart").data([data]);
|
197
|
-
//
|
198
|
-
// // Otherwise, create the skeletal chart.
|
199
|
-
// var gEnter = svg.enter().append("svg").append("g");
|
200
|
-
// gEnter.append("g").attr("class", "bars");
|
201
|
-
// gEnter.append("g").attr("class", "x axis");
|
202
|
-
//
|
203
|
-
// // // Update the outer dimensions.
|
204
|
-
// // svg .attr("width", width)
|
205
|
-
// // .attr("height", height);
|
206
|
-
// //
|
207
|
-
// // // Update the inner dimensions.
|
208
|
-
// var g = svg.select("g")
|
209
|
-
// .attr("transform", "translate(" + ca.x + "," + ca.y + ca.h + ")");
|
210
|
-
//
|
211
|
-
// // Update the bars.
|
212
|
-
// var bar = svg.select(".bars").selectAll(".bar").data(data);
|
213
|
-
// bar.enter().append("rect");
|
214
|
-
// bar.exit().remove();
|
215
|
-
// bar .attr("width", x.rangeBand())
|
216
|
-
// .attr("x", function(d) { return x(d.x); })
|
217
|
-
// .attr("y", function(d) { return y(d.y); })
|
218
|
-
// .attr("height", function(d) { return y.range()[0] - y(d.y); })
|
219
|
-
// .order();
|
220
|
-
//
|
221
|
-
//
|
222
|
-
// // Update the x-axis.
|
223
|
-
// // g.select(".x.axis")
|
224
|
-
// // .attr("transform", "translate(0," + y.range()[0] + ")")
|
225
|
-
// // .call(xAxis);
|
226
|
-
// }
|
227
|
-
|
228
|
-
}) // end of histogram
|
229
|
-
}) // end of provide
|
@@ -1,342 +0,0 @@
|
|
1
|
-
L.provide('OML.line_chart', ["graph/abstract_chart", "#OML.abstract_chart", "graph.css", ["/resource/vendor/d3/d3.js", "/resource/vendor/d3/d3.time.js"]], function () {
|
2
|
-
|
3
|
-
var o = OML;
|
4
|
-
|
5
|
-
|
6
|
-
OML['line_chart'] = OML.abstract_chart.extend({
|
7
|
-
decl_properties: [
|
8
|
-
['x_axis', 'key', {property: 'x'}],
|
9
|
-
['y_axis', 'key', {property: 'y'}],
|
10
|
-
['group_by', 'key', {property: 'id', optional: true}],
|
11
|
-
['stroke_width', 'int', 2],
|
12
|
-
['stroke_color', 'color', 'black'],
|
13
|
-
['stroke_fill', 'color', 'blue']
|
14
|
-
],
|
15
|
-
|
16
|
-
base_css_class: 'oml-line-chart',
|
17
|
-
|
18
|
-
configure_base_layer: function(vis) {
|
19
|
-
//OML.abstract_chart.prototype.initialize.call(this, opts);
|
20
|
-
var base_layer = this.base_layer = vis.append("svg:g")
|
21
|
-
.attr("transform", "translate(0, " + this.h + ")");
|
22
|
-
|
23
|
-
|
24
|
-
var ca = this.chart_area;
|
25
|
-
//var g = this.base_layer;
|
26
|
-
|
27
|
-
this.legend_layer = base_layer.append("svg:g");
|
28
|
-
var g = this.chart_layer = base_layer.append("svg:g");
|
29
|
-
g.append("svg:line")
|
30
|
-
.attr("class", "xAxis axis")
|
31
|
-
.attr("x1", ca.x)
|
32
|
-
.attr("y1", -1 * ca.y)
|
33
|
-
.attr("x2", ca.x + ca.w)
|
34
|
-
.attr("y2", -1 * ca.y);
|
35
|
-
|
36
|
-
g.append("svg:line")
|
37
|
-
.attr("class", "yAxis axis")
|
38
|
-
.attr("x1", ca.x)
|
39
|
-
.attr("y1", -1 * ca.y)
|
40
|
-
.attr("x2", ca.x)
|
41
|
-
.attr("y2", -1 * (ca.y + ca.h));
|
42
|
-
},
|
43
|
-
|
44
|
-
|
45
|
-
redraw: function(data) {
|
46
|
-
var self = this;
|
47
|
-
|
48
|
-
|
49
|
-
var o = this.opts;
|
50
|
-
var ca = this.widget_area;
|
51
|
-
var m = this.mapping;
|
52
|
-
|
53
|
-
/* GENERALIZE THIS */
|
54
|
-
var stroke_color_f = d3.scale.category10();
|
55
|
-
m.stroke_color = function(d, i) {
|
56
|
-
return stroke_color_f(i);
|
57
|
-
};
|
58
|
-
|
59
|
-
//this.color = o['color'] || d3.scale.category10();
|
60
|
-
|
61
|
-
/* 'data' should be an an array (each line) of arryas (each tuple)
|
62
|
-
* The following code assumes that the tuples are sorted in ascending
|
63
|
-
* value associated with the x-axis.
|
64
|
-
*/
|
65
|
-
var x_index = m.x_axis;
|
66
|
-
var y_index = m.y_axis;
|
67
|
-
var group_by = m.group_by;
|
68
|
-
if (group_by != null) {
|
69
|
-
data = this.group_by(data, group_by);
|
70
|
-
} else {
|
71
|
-
data = [data];
|
72
|
-
};
|
73
|
-
|
74
|
-
// The following assumes that the data is sorted in ascending value for x_axis
|
75
|
-
var x_max = this.x_max = o.xmax != undefined ? o.xmax : d3.max(data, function(d) {
|
76
|
-
var last = d[d.length - 1];
|
77
|
-
var x = x_index(last);
|
78
|
-
return x;
|
79
|
-
});
|
80
|
-
var x_max_cnt = d3.max(data, function(d) {return d.length});
|
81
|
-
var x_min = this.x_min = o.xmin != undefined ? o.xmin : d3.min(data, function(d) {return x_index(d[0]);});
|
82
|
-
var x = this.x = d3.scale.linear().domain([x_min, x_max]).range([ca.x, ca.x + ca.w]);
|
83
|
-
|
84
|
-
if (x_max_cnt > ca.w) {
|
85
|
-
// To much data, downsample
|
86
|
-
var data2 = [];
|
87
|
-
data.map(function(l) {
|
88
|
-
var xcurr = -999999;
|
89
|
-
var l2 = [];
|
90
|
-
l.map(function(t) {
|
91
|
-
var x = Math.round(self.x(x_index(t)));
|
92
|
-
if (x > xcurr) {
|
93
|
-
l2.push(t);
|
94
|
-
//xcurr = x + 1; // add a 'spare' pixel between consecutive points
|
95
|
-
xcurr = x;
|
96
|
-
}
|
97
|
-
});
|
98
|
-
data2.push(l2);
|
99
|
-
});
|
100
|
-
data = data2;
|
101
|
-
}
|
102
|
-
|
103
|
-
|
104
|
-
// var x_min = this.x_min = d3.min(data, function(d) {return d3.min(d, function(d) {return d.x})});
|
105
|
-
var y_max = this.y_max = o.ymax != undefined ? o.ymax : d3.max(data, function(s) {return d3.max(s, function(t) {return y_index(t)})});
|
106
|
-
var y_min = this.y_min = o.ymin != undefined ? o.ymin : d3.min(data, function(s) {return d3.min(s, function(t) {return y_index(t)})});
|
107
|
-
var y = this.y = d3.scale.linear().domain([y_min, y_max]).range([ca.y, ca.y + ca.h]);
|
108
|
-
|
109
|
-
|
110
|
-
//var stroke_width = o.stroke_width ? o.stroke_width : 2;
|
111
|
-
var line = d3.svg.line()
|
112
|
-
.x(function(t) { return x(x_index(t)) })
|
113
|
-
.y(function(t) { return -1 * y(y_index(t)); })
|
114
|
-
;
|
115
|
-
|
116
|
-
var self = this;
|
117
|
-
var lines = this.chart_layer.selectAll(".chart")
|
118
|
-
.data(data, function(d, i) { return i; })
|
119
|
-
.attr("d", function(d) { return line(d); });
|
120
|
-
lines.enter()
|
121
|
-
.append("svg:path")
|
122
|
-
.attr("stroke-width", m.stroke_width)
|
123
|
-
.attr("d", function(d) {
|
124
|
-
var l = line(d);
|
125
|
-
return l;
|
126
|
-
})
|
127
|
-
|
128
|
-
.attr("class", "chart")
|
129
|
-
.attr("stroke", m.stroke_color)
|
130
|
-
.attr("fill", "none")
|
131
|
-
.on("mouseover", function(data) {
|
132
|
-
var group_by = self.mapping.group_by;
|
133
|
-
if (group_by) {
|
134
|
-
var name = group_by(data[0]);
|
135
|
-
self.on_highlighted({'elements': [{'id': name}]});
|
136
|
-
}
|
137
|
-
})
|
138
|
-
.on("mouseout", function() {
|
139
|
-
self.on_dehighlighted({});
|
140
|
-
})
|
141
|
-
;
|
142
|
-
lines.exit().remove();
|
143
|
-
|
144
|
-
|
145
|
-
this.update_ticks();
|
146
|
-
this.update_selection({});
|
147
|
-
},
|
148
|
-
|
149
|
-
on_highlighted: function(evt) {
|
150
|
-
var els = evt.elements;
|
151
|
-
var names = _.map(els, function(el) { return el.id});
|
152
|
-
var vis = this.chart_layer;
|
153
|
-
var group_by = this.mapping.group_by;
|
154
|
-
if (group_by) {
|
155
|
-
vis.selectAll(".chart")
|
156
|
-
.filter(function(d) {
|
157
|
-
var dname = group_by(d[0]);
|
158
|
-
return ! _.include(names, dname);
|
159
|
-
})
|
160
|
-
.transition()
|
161
|
-
.style("opacity", 0.1)
|
162
|
-
.delay(0)
|
163
|
-
.duration(300);
|
164
|
-
}
|
165
|
-
if (evt.source == null) {
|
166
|
-
evt.source = this;
|
167
|
-
OHUB.trigger("graph.highlighted", evt);
|
168
|
-
}
|
169
|
-
},
|
170
|
-
|
171
|
-
on_dehighlighted: function(evt) {
|
172
|
-
var vis = this.chart_layer;
|
173
|
-
vis.selectAll(".chart")
|
174
|
-
.transition()
|
175
|
-
.style("opacity", 1.0)
|
176
|
-
.delay(0)
|
177
|
-
.duration(300)
|
178
|
-
if (evt.source == null) {
|
179
|
-
evt.source = this;
|
180
|
-
OHUB.trigger("graph.dehighlighted", evt);
|
181
|
-
}
|
182
|
-
},
|
183
|
-
|
184
|
-
|
185
|
-
clear: function(data) {
|
186
|
-
this.data = null;
|
187
|
-
var lines = this.chart_layer.selectAll(".chart")
|
188
|
-
.data([])
|
189
|
-
.exit().remove();
|
190
|
-
},
|
191
|
-
|
192
|
-
// Return a subset of the associated data set where the value mapped
|
193
|
-
// to the x-axis is within the <+min+, +max> range.
|
194
|
-
//
|
195
|
-
filter_x: function(min, max) {
|
196
|
-
var xi = this.mapping.x_axis;
|
197
|
-
return this.data.filter(function(t) {
|
198
|
-
var x = t[xi];
|
199
|
-
return (x > min && x <= max);
|
200
|
-
})
|
201
|
-
},
|
202
|
-
|
203
|
-
update_ticks: function() {
|
204
|
-
var y = this.y;
|
205
|
-
var x = this.x;
|
206
|
-
var g = this.base_layer;
|
207
|
-
var ca = this.chart_area;
|
208
|
-
|
209
|
-
var tick_length = 7;
|
210
|
-
var label_spacing = tick_length + 2;
|
211
|
-
|
212
|
-
var xa_opts = this.opts['xaxis'] || {};
|
213
|
-
var ya_opts = this.opts['yaxis'] || {};
|
214
|
-
|
215
|
-
var xTicksA = x.ticks(xa_opts['ticks'] || 5);
|
216
|
-
if (xa_opts['show_labels'] != false) {
|
217
|
-
// TODO: FIX ME!!!!
|
218
|
-
var xLabelOpts = xa_opts['label'];
|
219
|
-
var xFormat;
|
220
|
-
if (xLabelOpts) {
|
221
|
-
if (xLabelOpts.type == 'date') {
|
222
|
-
var xFormatter = d3.time.format(xLabelOpts.format || "%X");
|
223
|
-
xFormat = function(d) {
|
224
|
-
var date = new Date(1000 * d); // TODO: Implicitly assuming that value is in seconds is most likely NOT a good idea
|
225
|
-
var fs = xFormatter(date);
|
226
|
-
return fs;
|
227
|
-
}
|
228
|
-
} else {
|
229
|
-
var xFormatter = d3.format(xLabelOpts.format || "g");
|
230
|
-
xFormat = function(d) {
|
231
|
-
var fs = xFormatter(d);
|
232
|
-
return fs;
|
233
|
-
}
|
234
|
-
}
|
235
|
-
} else {
|
236
|
-
xFormat = function(d) {return d};
|
237
|
-
}
|
238
|
-
|
239
|
-
// xFormat = function(d) {
|
240
|
-
// var ds = "" + d;
|
241
|
-
// var date = new Date(1000 * d);
|
242
|
-
// var fs = tformat(date);
|
243
|
-
// return fs;
|
244
|
-
// }
|
245
|
-
|
246
|
-
var xLabel = g.selectAll(".xLabel")
|
247
|
-
.data(xTicksA)
|
248
|
-
.text(xFormat)
|
249
|
-
.attr("x", function(d) { return x(d) });
|
250
|
-
xLabel.enter().append("svg:text")
|
251
|
-
.attr("class", "xLabel")
|
252
|
-
.text(xFormat)
|
253
|
-
.attr("x", function(d) { return x(d) })
|
254
|
-
.attr("y", -1 * (ca.y - label_spacing))
|
255
|
-
.attr("text-anchor", "middle")
|
256
|
-
.attr("dominant-baseline", "text-before-edge");
|
257
|
-
xLabel.exit().remove();
|
258
|
-
|
259
|
-
var xTicks = g.selectAll(".xTicks")
|
260
|
-
.data(xTicksA)
|
261
|
-
.attr("x1", function(d) { return x(d); })
|
262
|
-
.attr("x2", function(d) { return x(d); })
|
263
|
-
xTicks.enter().append("svg:line")
|
264
|
-
.attr("class", "xTicks ticks")
|
265
|
-
.attr("x1", function(d) { return x(d); })
|
266
|
-
.attr("y1", -1 * ca.y)
|
267
|
-
.attr("x2", function(d) { return x(d); })
|
268
|
-
.attr("y2", -1 * (ca.y - tick_length));
|
269
|
-
xTicks.exit().remove();
|
270
|
-
};
|
271
|
-
|
272
|
-
if (xa_opts['show_grids'] != false) {
|
273
|
-
var xGrids = g.selectAll(".xGrids")
|
274
|
-
.data(xTicksA)
|
275
|
-
.attr("x1", function(d) { return x(d); })
|
276
|
-
.attr("x2", function(d) { return x(d); })
|
277
|
-
xGrids.enter().append("svg:line")
|
278
|
-
.attr("class", "xGrids grids")
|
279
|
-
.attr("x1", function(d) { return x(d); })
|
280
|
-
.attr("y1", -1 * ca.y)
|
281
|
-
.attr("x2", function(d) { return x(d); })
|
282
|
-
.attr("y2", -1 * (ca.h + ca.y));
|
283
|
-
xGrids.exit().remove();
|
284
|
-
};
|
285
|
-
|
286
|
-
var yTicksCnt = ya_opts['ticks'] ? ya_opts['ticks'] : (this.h / 30);
|
287
|
-
var yTicksA = y.ticks(yTicksCnt);
|
288
|
-
if (ya_opts['show_labels'] != false) {
|
289
|
-
var yFormat = ya_opts['label'] || function(d) {return d};
|
290
|
-
|
291
|
-
var yLabel = g.selectAll(".yLabel")
|
292
|
-
.data(yTicksA)
|
293
|
-
.text(yFormat)
|
294
|
-
.attr("y", function(d) { return -1 * y(d) })
|
295
|
-
yLabel.enter().append("svg:text")
|
296
|
-
.attr("class", "yLabel")
|
297
|
-
.text(yFormat)
|
298
|
-
.attr("x", ca.x - label_spacing)
|
299
|
-
.attr("y", function(d) { return -1 * y(d) })
|
300
|
-
.attr("text-anchor", "end")
|
301
|
-
.attr("dy", 4);
|
302
|
-
yLabel.exit().remove();
|
303
|
-
|
304
|
-
var yTicks = g.selectAll(".yTicks")
|
305
|
-
.data(yTicksA)
|
306
|
-
.attr("y1", function(d) { return -1 * y(d); })
|
307
|
-
.attr("y2", function(d) { return -1 * y(d); })
|
308
|
-
yTicks.enter().append("svg:line")
|
309
|
-
.attr("class", "yTicks ticks")
|
310
|
-
.attr("y1", function(d) { return -1 * y(d); })
|
311
|
-
.attr("x1", ca.x - tick_length)
|
312
|
-
.attr("y2", function(d) { return -1 * y(d); })
|
313
|
-
.attr("x2", ca.x);
|
314
|
-
yTicks.exit().remove();
|
315
|
-
}
|
316
|
-
|
317
|
-
if (ya_opts['show_grids'] != false) {
|
318
|
-
var yGrids = g.selectAll(".yGrids")
|
319
|
-
.data(yTicksA)
|
320
|
-
.attr("y1", function(d) { return -1 * y(d); })
|
321
|
-
.attr("y2", function(d) { return -1 * y(d); })
|
322
|
-
yGrids.enter().append("svg:line")
|
323
|
-
.attr("class", "yGrids grids")
|
324
|
-
.attr("stroke", "grey")
|
325
|
-
.attr("y1", function(d) { return -1 * y(d); })
|
326
|
-
.attr("x1", ca.x + ca.w)
|
327
|
-
.attr("y2", function(d) { return -1 * y(d); })
|
328
|
-
.attr("x2", ca.x);
|
329
|
-
yGrids.exit().remove();
|
330
|
-
}
|
331
|
-
},
|
332
|
-
|
333
|
-
})
|
334
|
-
})
|
335
|
-
|
336
|
-
/*
|
337
|
-
Local Variables:
|
338
|
-
mode: Javascript
|
339
|
-
tab-width: 2
|
340
|
-
indent-tabs-mode: nil
|
341
|
-
End:
|
342
|
-
*/
|