Git Product home page Git Product logo

chartkick's Introduction

Chartkick

Create beautiful JavaScript charts with one line of Ruby. No more fighting with charting libraries!

See it in action

🔥 For admin charts and dashboards, check out Blazer, and for advanced visualizations, check out Vega

💕 A perfect companion to Groupdate, Hightop, and ActiveMedian

Build Status

Quick Start

Add this line to your application’s Gemfile:

gem "chartkick"

Then follow the instructions for your JavaScript setup:

This sets up Chartkick with Chart.js. For other charting libraries and frameworks, see these instructions.

Importmap

In config/importmap.rb, add:

pin "chartkick", to: "chartkick.js"
pin "Chart.bundle", to: "Chart.bundle.js"

And in app/javascript/application.js, add:

import "chartkick"
import "Chart.bundle"

esbuild, rollup.js, or Webpack

Run:

yarn add chartkick chart.js

And in app/javascript/application.js, add:

import "chartkick/chart.js"

Note: For rollup.js, this requires format: "iife" in rollup.config.js.

Webpacker

Run:

yarn add chartkick chart.js

And in app/javascript/packs/application.js, add:

import "chartkick/chart.js"

Sprockets

In app/assets/javascripts/application.js, add:

//= require chartkick
//= require Chart.bundle

Charts

Line chart

<%= line_chart User.group_by_day(:created_at).count %>

Pie chart

<%= pie_chart Goal.group(:name).count %>

Column chart

<%= column_chart Task.group_by_hour_of_day(:created_at, format: "%l %P").count %>

Bar chart

<%= bar_chart Shirt.group(:size).sum(:price) %>

Area chart

<%= area_chart Visit.group_by_minute(:created_at).maximum(:load_time) %>

Scatter chart

<%= scatter_chart City.pluck(:size, :population) %>

Geo chart - Google Charts

<%= geo_chart Medal.group(:country).count %>

Timeline - Google Charts

<%= timeline [
  ["Washington", "1789-04-29", "1797-03-03"],
  ["Adams", "1797-03-03", "1801-03-03"],
  ["Jefferson", "1801-03-03", "1809-03-03"]
] %>

Multiple series

<%= line_chart [
  {name: "Workout", data: {"2021-01-01" => 3, "2021-01-02" => 4}},
  {name: "Call parents", data: {"2021-01-01" => 5, "2021-01-02" => 3}}
] %>

or

<%= line_chart Feat.group(:goal_id).group_by_week(:created_at).count %>

Data

Data can be a hash, array, or URL.

Hash

<%= line_chart({"2021-01-01" => 2, "2021-01-02" => 3}) %>

Array

<%= line_chart [["2021-01-01", 2], ["2021-01-02", 3]] %>

URL

Make your pages load super fast and stop worrying about timeouts. Give each chart its own endpoint.

<%= line_chart completed_tasks_charts_path %>

And in your controller, pass the data as JSON.

class ChartsController < ApplicationController
  def completed_tasks
    render json: Task.group_by_day(:completed_at).count
  end
end

For multiple series, add chart_json at the end.

render json: Task.group(:goal_id).group_by_day(:completed_at).count.chart_json

Options

Id, width, and height

<%= line_chart data, id: "users-chart", width: "800px", height: "500px" %>

Min and max values

<%= line_chart data, min: 1000, max: 5000 %>

min defaults to 0 for charts with non-negative values. Use nil to let the charting library decide.

Min and max for x-axis - Chart.js

<%= line_chart data, xmin: "2021-01-01", xmax: "2022-01-01" %>

Colors

<%= line_chart data, colors: ["#b00", "#666"] %>

Stacked columns or bars

<%= column_chart data, stacked: true %>

Discrete axis

<%= line_chart data, discrete: true %>

Label (for single series)

<%= line_chart data, label: "Value" %>

Axis titles

<%= line_chart data, xtitle: "Time", ytitle: "Population" %>

Straight lines between points instead of a curve

<%= line_chart data, curve: false %>

Hide points

<%= line_chart data, points: false %>

Show or hide legend

<%= line_chart data, legend: false %>

Specify legend position

<%= line_chart data, legend: "bottom" %>

Donut chart

<%= pie_chart data, donut: true %>

Prefix, useful for currency - Chart.js, Highcharts

<%= line_chart data, prefix: "$" %>

Suffix, useful for percentages - Chart.js, Highcharts

<%= line_chart data, suffix: "%" %>

Set a thousands separator - Chart.js, Highcharts

<%= line_chart data, thousands: "," %>

Set a decimal separator - Chart.js, Highcharts

<%= line_chart data, decimal: "," %>

Set significant digits - Chart.js, Highcharts

<%= line_chart data, precision: 3 %>

Set rounding - Chart.js, Highcharts

<%= line_chart data, round: 2 %>

Show insignificant zeros, useful for currency - Chart.js, Highcharts

<%= line_chart data, round: 2, zeros: true %>

Friendly byte sizes - Chart.js

<%= line_chart data, bytes: true %>

Specify the message when data is loading

<%= line_chart data, loading: "Loading..." %>

Specify the message when data is empty

<%= line_chart data, empty: "No data" %>

Refresh data from a remote source every n seconds

<%= line_chart url, refresh: 60 %>

You can pass options directly to the charting library with:

<%= line_chart data, library: {backgroundColor: "#eee"} %>

See the documentation for Chart.js, Google Charts, and Highcharts for more info. For Chart.js plugins, check out this guide.

To customize datasets in Chart.js, use:

<%= line_chart data, dataset: {borderWidth: 10} %>

You can pass this option to individual series as well.

Global Options

To set options for all of your charts, create an initializer config/initializers/chartkick.rb with:

Chartkick.options = {
  height: "400px",
  colors: ["#b00", "#666"]
}

Customize the html

Chartkick.options[:html] = '<div id="%{id}" style="height: %{height};">%{loading}</div>'

You capture the JavaScript in a content block with:

Chartkick.options[:content_for] = :charts_js

Then, in your layout, use:

<%= yield :charts_js %>

For Padrino, use yield_content instead of yield.

This is great for including all of your JavaScript at the bottom of the page.

Multiple Series

You can pass a few options with a series:

  • name
  • data
  • color
  • dataset - Chart.js only
  • points - Chart.js only
  • curve - Chart.js only

Code

If you want to use the charting library directly, get the code with:

<%= line_chart data, code: true %>

The code will be logged to the JavaScript console. JavaScript functions cannot be logged, so it may not be identical.

Download Charts

Chart.js only

Give users the ability to download charts. It all happens in the browser - no server-side code needed.

<%= line_chart data, download: true %>

Safari will open the image in a new window instead of downloading.

Set the filename

<%= line_chart data, download: {filename: "boom"} %>

Set the background color

<%= line_chart data, download: {background: "#ffffff"} %>

Set title

<%= line_chart data, title: "Awesome chart" %>

Additional Charting Libraries

Google Charts

In your layout or views, add:

<%= javascript_include_tag "https://www.gstatic.com/charts/loader.js" %>

For Importmap (Rails 7 default), in config/importmap.rb, add:

pin "chartkick", to: "chartkick.js"

And in app/javascript/application.js, add:

import "chartkick"

For Webpacker (Rails 6 default), run:

yarn add chartkick

And in app/javascript/packs/application.js, add:

import "chartkick"

For Sprockets, in app/assets/javascripts/application.js, add:

//= require chartkick

To specify a language or Google Maps API key, use:

Chartkick.configure({language: "de", mapsApiKey: "..."})

before your charts.

Highcharts

For Importmap (Rails 7 default), run:

bin/importmap pin highcharts --download

And in config/importmap.rb, add:

pin "chartkick", to: "chartkick.js"

And in app/javascript/application.js, add:

import "chartkick"
import Highcharts from "highcharts"

window.Highcharts = Highcharts

For Webpacker (Rails 6 default), run:

yarn add chartkick highcharts

And in app/javascript/packs/application.js, add:

import "chartkick/highcharts"

For Sprockets, download highcharts.js into vendor/assets/javascripts (or use yarn add highcharts in Rails 5.1+), and in app/assets/javascripts/application.js, add:

//= require chartkick
//= require highcharts

Multiple Libraries

If more than one charting library is loaded, choose between them with:

<%= line_chart data, adapter: "google" %> <!-- or highcharts or chartjs -->

Sinatra and Padrino

Download chartkick.js and include it manually.

<script src="chartkick.js"></script>

Then include the charting library.

Chart.js - download Chart.js and the date-fns adapter bundle

<script src="chart.js"></script>
<script src="chartjs-adapter-date-fns.bundle.js"></script>

Google Charts

<script src="https://www.gstatic.com/charts/loader.js"></script>

Highcharts - download highcharts.js

<script src="highcharts.js"></script>

JavaScript API

Access a chart with:

var chart = Chartkick.charts["chart-id"]

Get the underlying chart object with:

chart.getChartObject()

You can also use:

chart.getElement()
chart.getData()
chart.getOptions()
chart.getAdapter()

Update the data with:

chart.updateData(newData)

You can also specify new options:

chart.setOptions(newOptions)
// or
chart.updateData(newData, newOptions)

Refresh the data from a remote source:

chart.refreshData()

Redraw the chart with:

chart.redraw()

Destroy the chart with:

chart.destroy()

Loop over charts with:

Chartkick.eachChart(function (chart) {
  // do something
})

Content Security Policy (CSP)

Check out how to configure CSP

Tutorials

Upgrading

5.0

If you use Importmap or Sprockets, update the gem and you’re good to go!

If you use esbuild, Webpack, or Webpacker, run:

yarn upgrade chartkick --latest

If you use Chart.js with esbuild, Webpack, or Webpacker, also run:

yarn upgrade chart.js --latest

History

View the changelog

Contributing

Everyone is encouraged to help improve this project. Here are a few ways you can help:

To get started with development:

git clone https://github.com/ankane/chartkick.git
cd chartkick
bundle install
bundle exec rake test

chartkick's People

Contributors

alex-benoit avatar ankane avatar black-snow avatar cbdileo avatar ceclinux avatar coder2000 avatar compumike avatar detry322 avatar dpayonk avatar eliotsykes avatar epistrephein avatar federomero avatar guymaliar avatar jeanmartin avatar kirkelifson avatar kylemathews avatar lavode avatar maclover7 avatar mihoid avatar novtopro avatar ombr avatar printercu avatar tarraschk avatar timleppard avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

chartkick's Issues

Removing time from the datapoint

Hi.

I've been trying to remove the time in the data shown when you hover over a data point. I've tried using to_date and to_s on the date in the data but to no avail.

I've also checked if the data im using has a time together with the date (it doesn't. just has a date).

Is there a way (or i missed something) to remove the time? I need the data point to show only the date and the corresponding paired data (in this case, inventory).

chartkick-question

P.S. Really sorry. Dunno if this is the right place to ask this.

Customizing tooltips

Hi,

I'm using chartkick and group_date for a multiple series chart like the one in the readme, let's say:

<%= line_chart @users.map{|user| {:name => user.name, :data => user.orders.group_by_week(:created_at).average(:price)}
} %>

Is there a way to customize the tooltip via chartkick? (In the above example, I need to change date format and round price to the second decimal)

TIA

[suggestion] simplify examples

I think your examples shouldn't rely on the grouping gem. It'd be nice to see what the line_chart method is expecting without any other plugins involved. Something like

  1. make chart data hash
  2. pass chart data to line_chart of pie_chart method

I'm a pretty inexperienced rails dev, so maybe I'm missing something fundamental.

Feature request: discrete line/area chart

Hi,

using this library I noticed that there is no option to allow discrete line/area charts. It would be useful in some scenarios.

Since at the moment I don't need continuous charts, I switched time to false in processLineData and datetime to string in renderLineChart but it would be great if that could be configurable with an option

Grouping data by Month and Year? Example?

Is there any way to group data by two values?

Grouping data by month and year seems to not be handled very well. The best way i can figure to do it is with using Date() objects and each value is given a general full date for first of the month but you only show the month and year data.

I am dealing with data that looks like:
{"July"=>4, "August"=>120, "September"=>6, "October"=>10, "November"=>2, "June"=>1, "February"=>3, "March"=>5, "December"=>6, "May"=>1, "January"=>25, "April"=>72}

I would like to add year either as part of the month key name such as "July 2013" or possible as:
{"month" => "July", "year" => "2013", "count" => 4},{"month" => "September", "year" => "2013", "count" => 6}

Is there any suggestions on the best way to deal with this?

Turn off Labels

I'm new to web dev and this is more of a question then an issue. I'm trying to turn off the the vertical and horizontal labels but just can't get it right. Here is the code:

<%= column_chart Vehicle.group_by_month(:rego_due).count, :height => "150px", :library => { :backgroundColor => "#f5f5f5", :colors => ['#004d84', :hAxis => { :textPosition => 'none' } ]} %>

Is there a list of all the library members that can be accessed or an examples? Thanks

createDataTable Function needs to be rebuilt to support multiple columns

Currently the createDataTable function supports a single column type. Up tot this point this has been "String" for the purpose of the charts that are currently supported. But the createDataTable function needs to be rebuilt to allow multiple columns to be created. Example usage is for the timeline visualization that requires a Start and End data column. #39

Line chart x-axis values other than date and time

Hi,

Trying to create my first chart.
What I want to do is create a line chart with a series of data (no time or date associated with it)

Below lines did not work,

new Chartkick.LineChart("chart-1", { 11,6,3,2,8});
new Chartkick.LineChart("chart-1", { "1":11,"2":6,"3":3,"4":2,"5":8});

How can I make this work?

Cheers

Support for Chart.js?

Is it possible to add support for Chart.js?

I have no experience with submiting to opensource software, and dont know much of javascript; but with some help, i could do it.

Redrawing Charts

Is there currently a way to redraw a rendered chart with a simple js call? I'm wanting to make the charts more responsive and thought it could be an easy fix to attach a chart redraw function to window size event.

Issue when model contains a date field

Trying to use pie chart on a invoice model and because it contains a date field l get the following

PG::Error: ERROR: column "invoices.date" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: ... ORDER BY date DESC

Have tested on model without a date field and works fine

Date not displaying properly in area and line charts

Not sure if this has been fixed already (because I've seen other issues regarding this)...(I installed Chartkick about 5 days ago), but for some reason, I can't get chartkick to display the proper date (I'm using unix time, which I've converted to Ruby datetime)

This is the same data, in 3 different types of charts. For some reason, the column chart works, but the line and area don't.

screen shot 2014-02-11 at 10 06 50 am

Passing in custom options

Wow! Thank you for this gem. It's so nice and simple.

I browsed through the JS and Ruby helpers and I was wondering if it would be possible to pass in options via the Ruby helper which get passed into the Highcharts or Google Charts JS options. I tried something like:

<%= line_chart series, legend: { position: "left" } %>

Is this something that would work?

How to change the default language / locale for Google Charts?

I'm sorry if it's not an issue of chartkick, but after googling a bit I still have no clue.

What I want to do is set the default language to "zh" no matter what locales users use. So that the labels on line charts would be in Chinese.

According to Google's documentation, I should be able to set the language by using the language parameter:

google.load('visualization', '1', {'packages':['corechart'], 'language': 'ja'});

I tried with line_chart api_console_page_index_path, library: {language: "zh"} but it doesn't work.

Can you please help me?

Using javascript functions when passing options to library

Trying to do some advanced x-axis label formatting with with highcharts;

<%= column_chart weekly_samples_charts_path, library: {
  xAxis: {
    labels: {
      enabled: true,
      formatter: function() { ... }
    }
  }
} %>

but this failes, I get undefined method function' for #<#Class:0x007f8dd57e3258:0x007f8dd53cb8c8>` error.

Is this expected?

Associations attribute as value

Hey there,

I love the gem and thanks a lot for creating it. I am sorry if this issue is more technical support than an actual issue.

Diving right into it, I currently have a Projects model that has_many Tasks and each task belongs_to a User. The goal I am trying to achieve is to show how many tasks for a single project are assigned to each user.

This is already easily accomplished by doing this:

column_chart @project.tasks.group("user_id").count

However it is obviously displaying the ID of the user as the value and not one of the attributes on the user such as their email or full name. Is there a best use scenario for doing so?

Thanks!

Support for hash-as-values

Example JSON:

{
    "2013-05-20 03:02:30 UTC": {
        "bad": "3",
        "good": "4",
        "neutral": "10"
    },
    "2013-05-20 05:55:52 UTC": {
        "good": "1724",
        "total": "52072",
        "locatable": "20025",
        "unmatched": "51501"
    }
}

processSeries Check if 1 series of multiple needs to be rebuilt

    // see if one series or multiple
    if (!isArray(series) || typeof series[0] !== "object" || isArray(series[0])) {
      series = [{name: "Value", data: series}];
      opts.hideLegend = true;
    } else {
      opts.hideLegend = false;
    }

To support multiple columns of data rather than a max of 2 columns this if statement in chartkick.js needs to be rebuilt. The offending part of the statement is isArray(series[0])) which places the entire dataset into a object/hash.

Looking over the code i think a refactor would be beneficial to separate Data Manipulation and generation of the charts. Then use the process functions to call the needed manipulations and chart options as optional parameters

related: #42 and #43

formatting x-axis legend

This is an awesome library. Thanks!
I'm pretty new to Ruby, so this could be a horrible question. Sorry if this is the case.
I'm just curious if there is an easy way to update the x-axis labels with formatted strings? I'm building a big hourly date time chart and the x-axis labels are cluttered because its a pretty huge chart.

Any suggestions are greatly appreciated,

Thanks!

Nick

Decouple Chartkick from Railties?

I was hoping to use Chartkick with Padrino, which is a Sinatra-based framework that can be made Rails-like by including ActiveRecord, ActiveSupport, etc.

However, Chartkick won't run without Rack 1.4.5. Padrino requires Rack 1.5, and so I'm getting this error:

Bundler could not find compatible versions for gem "rack":
  In Gemfile:
    chartkick (>= 0) ruby depends on
      rack (~> 1.4.5) ruby

Haven't had a chance to play with Chartkick but it seems like it's something that could run with just ActiveRecord, just like the geocoder gem (https://github.com/alexreisner/geocoder)?

Chartkick is not defined

I have ChartKick referenced as outlined in the docs:

- content_for :head do
  = javascript_include_tag '//www.google.com/jsapi', 'chartkick'

(even referencing in head instead of at bottom of body!) and chartkick is not defined is being thrown. In the inspector, on line 355 of chartkick.js:

Uncaught TypeError: Cannot read property 'innerText' of undefined 

Any ideas?

Association in charts and pie chart theme

First thanks alot for this gem i have been trying for more than a month to create a dynamic gem but i always fail, but its easier with your gem thanks alot <3 .

Second I have Ticket model belongs_to employee_department and belongs_to state , i would like to show on pie chart the count of states (in state model i have :name attribute ) for each employee_department ( :name attribute ).

Third I used pie chart with one model it looks different from the one you have in the example ( your pie chart example shows with percentage and small squares ), how you change its theme ?

Note: I have <%= javascript_include_tag "/assets/highcharts.js", "chartkick" %>
thanks again for this gem 👍

Hide legend only when data given in single series format

We want to hide the legend when only graphing a single series, like:

<%= line_chart User.group_by_day(:created_at).count %>

However, if the data is provided as:

<%= line_chart @goals.map{|goal|
    {:name => goal.name, :data => goal.feats.group_by_week(:created_at).count }
} %>

and there is only one series, we still want to show the legend, since the title of the chart will be something like "Goals per Week".

Decouple Ruby and JS code

You should decouple Ruby and JS code so that other web languages (PHP, Python, ...) can build similar libraries based on the same JS.

URLs as data don't work

<%= line_chart [
   { name: "Total", data: statistics_path(key: "persons", subkey: "total") }
] 
%>

Produces a chart, but never hits the url.

Negative Values Function .data use?

  function negativeValues(series) {
    var i, j, data;
    for (i = 0; i < series.length; i++) {
      data = series[i].data;
      for (j = 0; j < data1.length; j++) {
        if (data[j][1] < 0) {
          return true;
        }
      }
    }
    return false;
  }

@ankane Can you explain what the .data is used for in the data = series[i].data; line?

The .data is causing a .data not defined error when i start creating the timeline. When i remove the .data everything appears to work correctly. I have never used the data other than with jquery. Is this supposed to be a jquery reference?

Return name rather than object?

Is there a way to display the name rather than an object?

For example: http://cl.ly/image/0F0Y1m200x2x

I'm using this code to produce the above chart.

<%= pie_chart Invoice.count(:group => "company") %>

If I change it to company.name I get an error that that column doesn't exist:

<%= pie_chart Invoice.count(:group => "company.name") %>

Mysql2::Error: Unknown column 'company.name' in 'field list'

Including JavaScript in the footer produces an error

First of all thanks for this super eay, quick setup gem! Works a charm even with turbolinks.

However Chartkick relies on having JavaScript loaded before the rest of the page. It returns an error when loaded in the footer or when using async="async", which are both best practices performance-wise.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.