Packages

Create beautiful JavaScript charts with one line of Elixir

Current section

7 Versions

Jump to

Compare versions

5 files changed
+107 additions
-94 deletions
  @@ -1,3 +1,7 @@
1 + ### 0.1.0
2 +
3 + * See [PR#3](https://github.com/buren/chartkick-ex/pull/3) - Thank you @mbenatti and @nimish-mehta
4 +
1 5 ### 0.0.2
2 6
3 7 * Removed defunct `ChartOptions` module.
  @@ -2,7 +2,7 @@
2 2
3 3 Create beautiful Javascript charts with one line of Elixir. No more fighting with charting libraries!
4 4
5 - [See it in action](http://buren.github.io/chartkick-ex/)
5 + [See it in action](http://buren.github.io/chartkick-ex/), you can find the example phoenix app that generates that page [here](https://github.com/buren/chartkick-phoenix-example).
6 6
7 7 Works with Phoenix, plain Elixir and most browsers (including IE 6).
8 8
  @@ -11,7 +11,8 @@ I'm _very_ new to Elixir, so if you have any feedback, suggestions or comments p
11 11 ## Charts
12 12
13 13 All charts expect a JSON string.
14 - ```
14 +
15 + ```elixir
15 16 data = Poison.encode!([[175, 60], [190, 80], [180, 75]])
16 17 ```
17 18
  @@ -126,7 +127,7 @@ See the documentation for [Google Charts](https://developers.google.com/chart/in
126 127 Pass data as a JSON string.
127 128
128 129 ```elixir
129 - Chartkick.pie_chart("{\"Football\" => 10, \"Basketball\" => 5}")
130 + Chartkick.pie_chart "{\"Football\" => 10, \"Basketball\" => 5}"
130 131 Chartkick.pie_chart "[[\"Football\", 10], [\"Basketball\", 5]]"
131 132 ```
132 133
  @@ -134,8 +135,8 @@ For multiple series, use the format
134 135
135 136 ```elixir
136 137 Chartkick.line_chart "[
137 - {name: \"Series A\", data: series_a},
138 - {name: \"Series B\", data: series_b}
138 + {name: \"Series A\", data: []},
139 + {name: \"Series B\", data: []}
139 140 ]"
140 141 ```
141 142
  @@ -153,12 +154,18 @@ Chartkick.line_chart "{
153 154 Add the following to your project :deps list:
154 155
155 156 ```elixir
156 - {:chartkick, "~>0.0.2"}
157 + {:chartkick, "~>0.1.0"}
157 158 ```
158 159
159 160 By default when you render a chart it will return both the HTML-element and JS that initializes the chart.
160 161 This will only work if you load Chartkick in the `<head>` tag.
161 162 You can chose to render the JS & HTML separately using the `only: :html` or `only: :script` option.
163 + Note that if you use those options you need to pass `id` otherwise it wont work.
164 +
165 + ```elixir
166 + line_chart data, id: "my-line-chart", only: :html
167 + line_chart data, id: "my-line-chart", only: :script
168 + ```
162 169
163 170 For Google Charts, use:
  @@ -1,16 +1,24 @@
1 1 {<<"app">>,<<"chartkick">>}.
2 2 {<<"build_tools">>,[<<"mix">>]}.
3 + {<<"description">>,
4 + <<"Create beautiful JavaScript charts with one line of Elixir">>}.
3 5 {<<"elixir">>,<<"~> 1.0">>}.
4 6 {<<"files">>,
5 - [<<"lib/chartkick.ex">>,<<"mix.exs">>,<<"README.md">>,<<"CHANGELOG.md">>]}.
7 + [<<"lib">>,<<"lib/chartkick.ex">>,<<"mix.exs">>,<<"README.md">>,
8 + <<"CHANGELOG.md">>]}.
9 + {<<"licenses">>,[<<"MIT">>]}.
10 + {<<"links">>,[{<<"GitHub">>,<<"https://github.com/buren/chartkick-ex">>}]}.
11 + {<<"maintainers">>,[<<"Jacob Burenstam">>]}.
6 12 {<<"name">>,<<"chartkick">>}.
7 13 {<<"requirements">>,
8 - [{<<"poison">>,
9 - [{<<"app">>,<<"poison">>},
10 - {<<"optional">>,false},
11 - {<<"requirement">>,<<"~> 1.5">>}]},
12 - {<<"uuid">>,
13 - [{<<"app">>,<<"uuid">>},
14 - {<<"optional">>,false},
15 - {<<"requirement">>,<<"~> 1.0">>}]}]}.
16 - {<<"version">>,<<"0.0.2">>}.
14 + [[{<<"app">>,<<"poison">>},
15 + {<<"name">>,<<"poison">>},
16 + {<<"optional">>,false},
17 + {<<"repository">>,<<"hexpm">>},
18 + {<<"requirement">>,<<"~> 3.0">>}],
19 + [{<<"app">>,<<"uuid">>},
20 + {<<"name">>,<<"uuid">>},
21 + {<<"optional">>,false},
22 + {<<"repository">>,<<"hexpm">>},
23 + {<<"requirement">>,<<"~> 1.1">>}]]}.
24 + {<<"version">>,<<"0.1.0">>}.
  @@ -1,80 +1,55 @@
1 1 defmodule Chartkick do
2 - def line_chart(data_source, options \\ []) do
3 - chartkick_chart("LineChart", data_source, options)
4 - end
2 + require EEx
5 3
6 - def pie_chart(data_source, options \\ []) do
7 - chartkick_chart("PieChart", data_source, options)
8 - end
9 -
10 - def column_chart(data_source, options \\ []) do
11 - chartkick_chart("ColumnChart", data_source, options)
12 - end
13 -
14 - def bar_chart(data_source, options \\ []) do
15 - chartkick_chart("BarChart", data_source, options)
16 - end
17 -
18 - def area_chart(data_source, options \\ []) do
19 - chartkick_chart("AreaChart", data_source, options)
20 - end
21 -
22 - def combo_chart(data_source, options \\ []) do
23 - chartkick_chart("ComboChart", data_source, options)
24 - end
25 -
26 - def geo_chart(data_source, options \\ []) do
27 - chartkick_chart("GeoChart", data_source, options)
28 - end
29 -
30 - def scatter_chart(data_source, options \\ []) do
31 - chartkick_chart("ScatterChart", data_source, options)
32 - end
33 -
34 - def timeline(data_source, options \\ []) do
35 - chartkick_chart("Timeline", data_source, options)
36 - end
37 -
38 - def chartkick_chart(klass, data_source, options \\ []) do
39 - id = options[:id] || generate_element_id
40 - height = options[:height] || "300px"
41 - only = options[:only]
42 - """
43 - #{unless only == :script, do: chartkick_tag(id, height)}
44 - #{unless only == :html, do: chartkick_script(klass, id, data_source, options_json(Enum.into(options, %{})))}
45 - """
46 - end
47 -
48 - def chartkick_script(klass, id, data_source, options_json) do
49 - "<script type=\"text/javascript\">new Chartkick.#{klass}('#{id}', #{data_source}, #{options_json});</script>"
50 - end
51 -
52 - def chartkick_tag(id, height) do
53 - "<div id=\"#{id}\" style=\"height: #{height}; text-align: center; color: #999; line-height: #{height}; font-size: 14px; font-family: 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif;\">Loading...</div>"
54 - end
55 -
56 - defp generate_element_id do
57 - UUID.uuid4()
58 - end
59 -
60 - defp options_json(opts) do
61 - map = %{}
62 - map = add_options_key(opts, map, :min)
63 - map = add_options_key(opts, map, :max)
64 - map = add_options_key(opts, map, :colors)
65 - map = add_options_key(opts, map, :stacked)
66 - map = add_options_key(opts, map, :discrete)
67 - map = add_options_key(opts, map, :xtitle)
68 - map = add_options_key(opts, map, :ytitle)
69 - Poison.encode!(map)
70 - end
71 -
72 - defp add_options_key(opts, map, key) do
73 - if Map.has_key?(opts, key) do
74 - Dict.put(map, key, opts[key])
75 - else
76 - map
4 + gen_chart_fn = fn (chart_type) ->
5 + def unquote(
6 + chart_type
7 + |> Macro.underscore
8 + |> String.to_atom
9 + )(data_source, options \\ []) do
10 + chartkick_chart(unquote(chart_type), data_source, options)
77 11 end
78 12 end
79 13
14 + Enum.map(
15 + ~w(LineChart PieChart BarChart AreaChart ColumnChart ComboChart GeoChart ScatterChart Timeline),
16 + gen_chart_fn
17 + )
18 +
19 + def chartkick_chart(klass, data_source, options \\ []) do
20 + id = Keyword.get_lazy(options, :id, &UUID.uuid4/0)
21 + height = Keyword.get(options, :height, "300px")
22 + only = Keyword.get(options, :only)
23 + case only do
24 + :html -> chartkick_tag(id, height)
25 + :script -> chartkick_script(klass, id, data_source, options_json(options))
26 + _ -> """
27 + #{ chartkick_tag(id, height) }
28 + #{ chartkick_script(klass, id, data_source, options_json(options)) }
29 + """
30 + end
31 + end
32 +
33 + EEx.function_from_string(
34 + :def,
35 + :chartkick_script,
36 + ~s[<script type="text/javascript">new Chartkick.<%= klass %>('<%= id %>', <%= data_source %>, <%= options_json %>);</script>],
37 + ~w(klass id data_source options_json)a
38 + )
39 +
40 + EEx.function_from_string(
41 + :def,
42 + :chartkick_tag,
43 + ~s[<div id="<%= id %>" style="height: <%= height %>; text-align: center; color: #999; line-height: <%= height %>; font-size: 14px; font-family: 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif;">Loading...</div>],
44 + ~w(id height)a
45 + )
46 +
47 + @options ~w(min max colors stacked discrete xtitle ytitle)a
48 + defp options_json(opts) do
49 + opts
50 + |> Keyword.take(@options)
51 + |> Enum.into(%{})
52 + |> Poison.encode!()
53 + end
54 +
80 55 end
  @@ -3,11 +3,14 @@ defmodule Chartkick.Mixfile do
3 3
4 4 def project do
5 5 [app: :chartkick,
6 - version: "0.0.2",
6 + version: "0.1.0",
7 7 elixir: "~> 1.0",
8 8 build_embedded: Mix.env == :prod,
9 9 start_permanent: Mix.env == :prod,
10 - deps: deps]
10 + package: package,
11 + description: description,
12 + licenses: "MIT",
13 + deps: deps()]
11 14 end
12 15
13 16 # Configuration for the OTP application
  @@ -17,6 +20,22 @@ defmodule Chartkick.Mixfile do
17 20 [applications: [:logger]]
18 21 end
19 22
23 + defp description do
24 + """
25 + Create beautiful JavaScript charts with one line of Elixir
26 + """
27 + end
28 +
29 + defp package do
30 + [
31 + licenses: ["MIT"],
32 + maintainers: ["Jacob Burenstam"],
33 + links: %{
34 + "GitHub" => "https://github.com/buren/chartkick-ex"
35 + }
36 + ]
37 + end
38 +
20 39 # Dependencies can be Hex packages:
21 40 #
22 41 # {:mydep, "~> 0.3.0"}
  @@ -27,7 +46,7 @@ defmodule Chartkick.Mixfile do
27 46 #
28 47 # Type `mix help deps` for more examples and options
29 48 defp deps do
30 - [{ :uuid, "~> 1.0" },
31 - {:poison, "~> 1.5"}]
49 + [{ :uuid, "~> 1.1" },
50 + {:poison, "~> 3.0"}]
32 51 end
33 52 end