pi_charts 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require "pi_charts"
3
+
4
+ # create a new pie chart
5
+ chart = PiCharts::Pie.new
6
+
7
+ # add datasets
8
+ chart.add_dataset(label: "cats", data: 80)
9
+ chart.add_dataset(label: "dogs", data: 20)
10
+
11
+ # make cats 90
12
+ chart.add_dataset(label: "cats", data: 10, add: true)
13
+
14
+ # make dogs 10, not adding
15
+ chart.add_dataset(label: "dogs", data: 10)
16
+
17
+ # neat 'lil configurations
18
+ chart.hover
19
+ chart.responsive
20
+
21
+ # generate html / js for chart
22
+ puts chart.html
@@ -0,0 +1,19 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require "pi_charts"
3
+
4
+ # create a new pie chart
5
+ chart = PiCharts::Pie.new
6
+
7
+ # add datasets
8
+ chart.add_dataset(label: "cats", data: 80)
9
+ chart.add_dataset(label: "dogs", data: 20)
10
+
11
+ # hide legend
12
+ chart.legend(hidden: true)
13
+
14
+ # neat 'lil configurations
15
+ chart.hover
16
+ chart.responsive
17
+
18
+ # generate html / js for chart
19
+ puts chart.html
@@ -0,0 +1,35 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'sinatra'
3
+ require 'pi_charts'
4
+
5
+ # whatever sinatra configurations you want
6
+ set :bind, '0.0.0.0'
7
+ set :port, 4567
8
+
9
+ # create a new line chart
10
+ chart = PiCharts::Line.new
11
+
12
+ # add labels ( x values )
13
+ chart.add_labels(["January", "February", "March", "April", "May"])
14
+
15
+ # add datasets
16
+ chart.add_dataset(label: "cats", data: [3, 1, 3, 3, 7])
17
+ chart.add_dataset(label: "dogs", data: [7, 3, 3, 1, 3])
18
+
19
+ # neat 'lil configurations
20
+ chart.hover
21
+ chart.responsive
22
+
23
+ # generate html / js for chart
24
+ # and serve it up, on the house ( localhost )
25
+
26
+ def bake_pie
27
+ chart = PiCharts::Pie.new
28
+ chart.add_dataset(label: "cats", data: 80)
29
+ chart.add_dataset(label: "dogs", data: 50)
30
+ chart.hover
31
+ chart.responsive
32
+ "<head>" + chart.cdn + "</head>" + "<body>" + chart.html(width: 100) + "</body>"
33
+ end
34
+
35
+ get('/serve_pie') { bake_pie }
@@ -0,0 +1,55 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'pi_charts'
3
+ require 'sinatra'
4
+
5
+ # whatever sinatra configurations you want
6
+ set :bind, '0.0.0.0'
7
+ set :port, 4567
8
+
9
+ utils = PiCharts::Utils.new
10
+
11
+ get('/') { "try /line or /pie or /bar" }
12
+
13
+ def line
14
+ chart = PiCharts::Line.new
15
+ chart.add_labels(["January", "February", "March", "April", "May"])
16
+ chart.add_dataset(label: "cats", data: [3, 1, 3, 3, 7])
17
+ chart.add_dataset(label: "dogs", data: [7, 3, 3, 1, 3])
18
+ chart.hover
19
+ chart.responsive
20
+ chart.html(width: 100)
21
+ end
22
+ get('/line') { "<head>" + utils.cdn + "</head>" + "<body>" + line + "</body>" }
23
+
24
+ def bake_pie
25
+ chart = PiCharts::Pie.new
26
+ chart.add_dataset(label: "cats", data: 80)
27
+ chart.add_dataset(label: "dogs", data: 50)
28
+ chart.hover
29
+ chart.responsive
30
+ chart.html(width: 100)
31
+ end
32
+ get('/pie') { "<head>" + utils.cdn + "</head>" + "<body>" + bake_pie + "</body>" }
33
+
34
+ def bar
35
+ chart = PiCharts::Bar.new
36
+ chart.add_labels(["January", "February", "March", "April", "May"])
37
+ chart.add_dataset(label: "cats", data: [ 2, 0, 4, 7, 3 ])
38
+ chart.add_dataset(label: "dogs", data: [ 4, 6, 3, 9, 2 ])
39
+ chart.stack
40
+ chart.hover
41
+ chart.responsive
42
+ chart.html(width: 100)
43
+ end
44
+ get('/bar') { "<head>" + utils.cdn + "</head>" + "<body>" + bar + "</body>" }
45
+
46
+ def get_doughnuts
47
+ chart = PiCharts::Doughnut.new
48
+ chart.add_dataset(label: "cats", data: 7)
49
+ chart.add_dataset(label: "dogs", data: 13)
50
+ chart.hover
51
+ chart.responsive
52
+ chart.html(width: 100)
53
+ end
54
+ get('/doughnut') { "<head>" + utils.cdn + "</head>" + "<body>" + get_doughnuts + "</body>" }
55
+
@@ -0,0 +1,25 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'pi_charts'
3
+ require 'sinatra'
4
+
5
+ # whatever sinatra configurations you want
6
+ set :bind, '0.0.0.0'
7
+ set :port, 4567
8
+
9
+ # create a new line chart
10
+ chart = PiCharts::Line.new
11
+
12
+ # add labels ( x values )
13
+ chart.add_labels(["January", "February", "March", "April", "May"])
14
+
15
+ # add datasets
16
+ chart.add_dataset(label: "cats", data: [3, 1, 3, 3, 7])
17
+ chart.add_dataset(label: "dogs", data: [7, 3, 3, 1, 3])
18
+
19
+ # neat 'lil configurations
20
+ chart.hover
21
+ chart.responsive
22
+
23
+ # generate html / js for chart
24
+ # and serve it up, on the house ( localhost )
25
+ get('/') { "<head>" + chart.cdn + "</head>" + "<body>" + chart.html(width: 100) + "</body>" }
@@ -0,0 +1,19 @@
1
+ # I guess I could do a loop, jah feel?
2
+ # Or any other way I guess.
3
+ require "pi_charts/version"
4
+ require "pi_charts/base"
5
+ require "pi_charts/utils"
6
+ require "pi_charts/config"
7
+ require "pi_charts/line_chart"
8
+ require "pi_charts/pie_chart"
9
+ require "pi_charts/bar_chart"
10
+ require "pi_charts/doughnut_chart"
11
+
12
+ # Lil' extra spice.
13
+ require "securerandom"
14
+ require "json"
15
+
16
+ module PiCharts
17
+ # I'll put my code where I want to put my code, thank you very much.
18
+ end
19
+
@@ -0,0 +1,125 @@
1
+ module PiCharts
2
+
3
+ class Bar < Base
4
+
5
+ def add_labels(labels)
6
+ @config.data[:data][:labels] = labels
7
+ end
8
+
9
+ def title(args={})
10
+ if args.keys.empty? or ! args.keys.include? [:title]
11
+ raise "need to specify title with {title: 'name', display: true/false }"
12
+ end
13
+ @config.data[:data][:options][:title] = {}
14
+ @config.data[:data][:options][:title][:text] = args[:title] || ""
15
+ @config.data[:data][:options][:title][:display] = true unless args[:display] == false
16
+ true
17
+ end
18
+
19
+ def create(args={})
20
+ @config.data[:type] = 'bar'
21
+ @config.data[:data][:datasets] = []
22
+ @config.data[:data][:labels] = []
23
+ true
24
+ end
25
+
26
+ def stack(args={})
27
+ @config.data[:options][:scales] = {} unless @config.data[:options][:scales]
28
+ @config.data[:options][:scales][:xAxes] = [] unless @config.data[:options][:scales][:xAxes]
29
+ @config.data[:options][:scales][:yAxes] = [] unless @config.data[:options][:scales][:yAxes]
30
+ if args.keys.empty?
31
+ @config.data[:options][:scales][:xAxes] << { stacked: true }
32
+ @config.data[:options][:scales][:yAxes] << { stacked: true }
33
+ else
34
+ @config.data[:options][:scales][:xAxes] << { stacked: true } if args[:x]
35
+ @config.data[:options][:scales][:yAxes] << { stacked: true } if args[:y]
36
+ end
37
+ end
38
+
39
+ def add_dataset(args={})
40
+ if args.keys.empty?
41
+ raise "need to specify dataset"
42
+ end
43
+ label = args[:label]
44
+ data = args[:data]
45
+ color = args[:color] || random_color
46
+ index = dataset_index(label)
47
+ if index
48
+ if data.kind_of?(Array)
49
+ data.each { |d| @config.data[:data][:datasets][index][:data] << d }
50
+ else
51
+ @config.data[:data][:datasets][index][:data] << data
52
+ end
53
+ else
54
+ dataset = {}
55
+ dataset[:label] = label
56
+ dataset[:borderColor] = color
57
+ dataset[:backgroundColor] = color
58
+ dataset[:data] = []
59
+ if data.kind_of?(Array)
60
+ data.each { |d| dataset[:data] << d }
61
+ else
62
+ dataset[:data] << data
63
+ end
64
+ @config.data[:data][:datasets] << dataset
65
+ end
66
+ true
67
+ end
68
+
69
+ def border(args={})
70
+ if args.keys.empty?
71
+ false
72
+ else
73
+ if args[:dataset]
74
+ index = dataset_index(args[:dataset])
75
+ if index
76
+ @config.data[:data][:datasets][index][:borderColor] = args[:color] if args[:color]
77
+ @config.data[:data][:datasets][index][:borderWidth] = args[:width] if args[:width]
78
+ @config.data[:data][:datasets][index][:borderSkipped] = args[:skipped] if args[:skipped]
79
+ @config.data[:data][:datasets][index][:borderDash] = args[:dash] if args[:dash]
80
+ else
81
+ raise "dataset doesn't seem to exist"
82
+ end
83
+ else
84
+ raise "need to specify a dataset"
85
+ end
86
+ end
87
+ end
88
+
89
+ def hover(args={})
90
+ if args.keys.empty?
91
+ false
92
+ else
93
+ if args[:dataset]
94
+ index = dataset_index(args[:dataset])
95
+ if index
96
+ @config.data[:data][:datasets][index][:hoverBackgroundColor] = args[:color] if args[:color]
97
+ @config.data[:data][:datasets][index][:hoverBorderColor] = args[:border] if args[:border]
98
+ @config.data[:data][:datasets][index][:hoverBorderWidth] = args[:width] if args[:width]
99
+ else
100
+ raise "dataset doesn't seem to exist"
101
+ end
102
+ else
103
+ raise "need to specify a dataset"
104
+ end
105
+ end
106
+ end
107
+
108
+ private
109
+
110
+ def dataset_index(label=false)
111
+ if label
112
+ @config.data[:data][:datasets].each_with_index do |set, index|
113
+ if set[:label] == label
114
+ return index
115
+ end
116
+ end
117
+ end
118
+ false
119
+ end
120
+
121
+
122
+ end
123
+
124
+
125
+ end
@@ -0,0 +1,98 @@
1
+ module PiCharts
2
+ # The Base class is responsible for providing the boiler plate
3
+ # code for all of the different types of +PiCharts+ that someone
4
+ # can create with this gem. That's its job.
5
+ class Base
6
+ attr_accessor :config # Configuration base for all charts.
7
+ attr_accessor :cdn # Content distribution network, for the lulz.
8
+
9
+ # Every class has a +config+ and, depending on the type
10
+ # the +create+ method will help with setting up the +config+
11
+ # for that specific type of chart.
12
+ def initialize(args = {})
13
+ @config = Config.new
14
+ create
15
+ end
16
+
17
+ # The responsive() method will make any chart responsive.
18
+ def responsive(responsive = true)
19
+ if responsive
20
+ config.data[:options][:responsive] = true
21
+ else
22
+ config.data[:options][:responsive] = false
23
+ end
24
+ end
25
+
26
+ # The cdn() method will generate a bit of html magic to create
27
+ # a cloudflare cdn link for the needed javascript.
28
+ def cdn(args = {})
29
+ version = args[:version] || '2.4.0'
30
+ min = false || args[:min]
31
+ if min
32
+ "<script src=\"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/#{version}/Chart.min.js\"></script>"
33
+ else
34
+ "<script src=\"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/#{version}/Chart.js\"></script>"
35
+ end
36
+ end
37
+
38
+ # The legend() provides an interface to set options for the legend for any chart.
39
+ def legend(args = {})
40
+ config.data[:options][:legend] = {} unless config.data[:options][:legend]
41
+ config.data[:options][:legend][:position] = args[:position] if args [:position]
42
+ config.data[:options][:legend][:display] = true if args[:display]
43
+ config.data[:options][:legend][:display] = false if args[:hidden]
44
+ config.data[:options][:legend][:fullWidth] = true if args[:full]
45
+ config.data[:options][:legend][:reverse] = true if args[:reverse]
46
+ # legend labels
47
+ config.data[:options][:legend][:labels][:boxWidth] = args[:width] if args[:width]
48
+ config.data[:options][:legend][:labels][:fontSize] = args[:size] if args[:size]
49
+ config.data[:options][:legend][:labels][:fontStyle] = args[:style] if args[:style]
50
+ config.data[:options][:legend][:labels][:padding] = args[:padding] if args[:padding]
51
+ end
52
+
53
+ # The hover() method provides an interface +that is currently incomplete+ to the hover options for a chart.
54
+ def hover(args = {})
55
+ config.data[:options][:hover] = {}
56
+ if args.keys.empty?
57
+ config.data[:options][:hover][:mode] = 'nearest'
58
+ config.data[:options][:hover][:intersect] = true
59
+ else
60
+ config.data[:options][:hover][:mode] = 'nearest' if args[:nearest]
61
+ config.data[:options][:hover][:intersect] = true if args[:intersect]
62
+ config.data[:options][:hover][:animationDuration] = args[:animation] if args[:animation]
63
+ end
64
+ # TODO: add support for onHover configuration option
65
+ true
66
+ end
67
+
68
+ # Sometimes you just need a random color.
69
+ def random_color
70
+ "##{SecureRandom.hex(3)}"
71
+ end
72
+
73
+ # The create() method helps with the main boiler-plate
74
+ # buisness that goes behind the Base class.
75
+ def create
76
+ # helps with boilerplateness
77
+ end
78
+
79
+ # The html() method helps build the relevant html for the chart.
80
+ def html(args = {})
81
+ id = SecureRandom.uuid
82
+ width = args[:width] || "50"
83
+ config = args[:config] || @config.json
84
+ type = @config.type
85
+
86
+ "<div id=\"canvas-holder\" style=\"width:#{width}%\">
87
+ <canvas id=\"#{id}\" />
88
+ </div>
89
+ <script>
90
+ var config = #{config}
91
+ window.onload = function() {
92
+ var ctx = document.getElementById(\"#{id}\").getContext(\"2d\");
93
+ new Chart(ctx, config);
94
+ };
95
+ </script>"
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,40 @@
1
+ module PiCharts
2
+
3
+ # The Config class provides the interface to the config
4
+ # for a chart. This is basically the skeleton of the
5
+ # infromation that drives the infromation for the chart
6
+ # that can be rendered into json. This information is
7
+ # constructed with its +data+ which actually provides
8
+ # the blueprints.
9
+ class Config
10
+ attr_accessor :data # The main brain and butter of what makes the co
11
+
12
+ # The initialize() method handles the creation of what defines
13
+ # the +data+ for a +config+, which sets up the relevant base.
14
+ def initialize(args={})
15
+ @data = {}
16
+ @data[:type] = ''
17
+ @data[:data] = {}
18
+ @data[:data][:datasets] = []
19
+ @data[:options] = {}
20
+ end
21
+
22
+ # type?() helps determine if a type has been set or not.
23
+ def type?
24
+ @data[:type].empty? ? false : true
25
+ end
26
+
27
+ # type() returns the the type set in the config, or false
28
+ # if a type has not yet been set.
29
+ def type
30
+ @data[:type].empty? ? false : @data[:type]
31
+ end
32
+
33
+ # json() returns the +json+ representation of the +config+ data
34
+ # in a javascript friendly form. Magic!
35
+ def json
36
+ @data.to_json
37
+ end
38
+
39
+ end
40
+ end