Current section
7 Versions
Jump to
Current section
7 Versions
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 |