phantom_graph 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZTlhZGJlNjc0OTllZDY4ZjFkZGRhNWUxNGUyN2YzOGQyOWE4ZmJhYg==
5
+ data.tar.gz: !binary |-
6
+ ZjRhMzI2YmRiMTUzOWNjZjlmMDRkZTlkMTU3NjY4ZTBhYjdmZGM5Yg==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NTlmMWFkY2U1YjFkM2EwNDdmM2Y3NzY4N2M0NTQ3M2Y1NmU0ZTE2ZjY3YzJl
10
+ YzdhYjA0MWI4YmU2MzY0MDM0YThmYjMxMzY5NDdjMjdhZDFlNmQxMjEwNDg0
11
+ ODBiNTUyZTExZGU1MjJjOGFjMWRkMjY2MTIwNDc5NmQzZjFhZTk=
12
+ data.tar.gz: !binary |-
13
+ M2JkNGNlMWJkZDhiMmU5NDYxYjI2MmMzYTVjMWMyZGQ3MDZmZDVhZThkNGM5
14
+ ZmIyZThiNDJhZmU5ZmY4OWMzZWYwNTNmYzRhODgzMGEzMmIzOTM2OTQ2Mzli
15
+ YzZlMTk1MTAwOGIxYjEyYzYzZWE3NzUzMTBhZGQ5YmFlZjIzZjM=
@@ -0,0 +1,7 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ test/dummy/db/*.sqlite3
5
+ test/dummy/log/*.log
6
+ test/dummy/tmp/
7
+ test/dummy/.sass-cache
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color spec
2
+ --profile
3
+ --format doc
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Declare your gem's dependencies in phantom_graph.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
7
+
8
+ # jquery-rails is used by the dummy application
9
+ gem "jquery-rails"
10
+
11
+ # Declare any dependencies that are still in development here instead of in
12
+ # your gemspec. These might include edge Rails or gems from your path or
13
+ # Git. Remember to move these dependencies to your gemspec before releasing
14
+ # your gem to rubygems.org.
15
+
16
+ # To use debugger
17
+ # gem 'debugger'
@@ -0,0 +1,78 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ phantom_graph (0.0.3)
5
+ json
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ actionpack (3.2.13)
11
+ activemodel (= 3.2.13)
12
+ activesupport (= 3.2.13)
13
+ builder (~> 3.0.0)
14
+ erubis (~> 2.7.0)
15
+ journey (~> 1.0.4)
16
+ rack (~> 1.4.5)
17
+ rack-cache (~> 1.2)
18
+ rack-test (~> 0.6.1)
19
+ sprockets (~> 2.2.1)
20
+ activemodel (3.2.13)
21
+ activesupport (= 3.2.13)
22
+ builder (~> 3.0.0)
23
+ activesupport (3.2.13)
24
+ i18n (= 0.6.1)
25
+ multi_json (~> 1.0)
26
+ builder (3.0.4)
27
+ diff-lcs (1.2.4)
28
+ erubis (2.7.0)
29
+ hike (1.2.3)
30
+ i18n (0.6.1)
31
+ journey (1.0.4)
32
+ jquery-rails (3.0.1)
33
+ railties (>= 3.0, < 5.0)
34
+ thor (>= 0.14, < 2.0)
35
+ json (1.8.0)
36
+ multi_json (1.7.7)
37
+ rack (1.4.5)
38
+ rack-cache (1.2)
39
+ rack (>= 0.4)
40
+ rack-ssl (1.3.3)
41
+ rack
42
+ rack-test (0.6.2)
43
+ rack (>= 1.0)
44
+ railties (3.2.13)
45
+ actionpack (= 3.2.13)
46
+ activesupport (= 3.2.13)
47
+ rack-ssl (~> 1.3.2)
48
+ rake (>= 0.8.7)
49
+ rdoc (~> 3.4)
50
+ thor (>= 0.14.6, < 2.0)
51
+ rake (10.1.0)
52
+ rdoc (3.12.2)
53
+ json (~> 1.4)
54
+ rspec (2.13.0)
55
+ rspec-core (~> 2.13.0)
56
+ rspec-expectations (~> 2.13.0)
57
+ rspec-mocks (~> 2.13.0)
58
+ rspec-core (2.13.1)
59
+ rspec-expectations (2.13.0)
60
+ diff-lcs (>= 1.1.3, < 2.0)
61
+ rspec-mocks (2.13.1)
62
+ sprockets (2.2.2)
63
+ hike (~> 1.2)
64
+ multi_json (~> 1.0)
65
+ rack (~> 1.0)
66
+ tilt (~> 1.1, != 1.3.0)
67
+ thor (0.18.1)
68
+ tilt (1.4.1)
69
+
70
+ PLATFORMS
71
+ ruby
72
+
73
+ DEPENDENCIES
74
+ jquery-rails
75
+ phantom_graph!
76
+ rack-test (>= 0.5.6)
77
+ rake (>= 0.9.2)
78
+ rspec (>= 2.2.0)
@@ -0,0 +1,20 @@
1
+ Copyright 2013 Yacobus Reinhart
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,72 @@
1
+ = PhantomGraph
2
+
3
+ PhantomGraph helps complex process to generate javascript charts to image or pdf without requesting or rendering view to the application.
4
+ PhantomGraph is pure server-side process by using phantomjs and suitable for background process.
5
+ It is lighweight solution for wkhtmltopdf alternative.
6
+
7
+ = Installation
8
+
9
+ gem 'phantom_graph'
10
+ or
11
+ gem install 'phantom_graph'
12
+
13
+ Do not forget to install phantomjs
14
+
15
+ See http://phantomjs.org/download.html on how to install phatomjs
16
+
17
+ = How To Use
18
+
19
+ add initialize file to "config/initializers/phantom_graph.rb"
20
+ ```
21
+ PhantomGraph.configure do |config|
22
+
23
+ # default: `which phantomjs` or `bundle exec which phantomjs`
24
+ config.phantomjs = "/usr/local/bin/phantomjs"
25
+
26
+ # default: false
27
+ config.logger = true
28
+
29
+ # Some javascript plugins are included in Gem
30
+ # if you override please change configuration below
31
+
32
+ # config.highcharts_convert_path = "/path/app/js/highcharts-convert.js"
33
+ # config.highcharts_theme_path = "/path/app/js/highcharts-theme.js"
34
+ # config.highcharts_path = "/path/app/js/highcharts.js"
35
+ # config.highstock_path = "/path/app/js/highstock.js"
36
+ # config.jquery_path = "/path/app/js/jquery.js"
37
+ end
38
+
39
+ === For more samples of json string or file please check:
40
+ * highchart json, please check: http://www.highcharts.com/demo/
41
+ * highstock json, please check: http://www.highcharts.com/stock/demo
42
+
43
+ ==== Highchart
44
+ # sample script: spec/phantom_graph/convert/highchart_spec.rb
45
+ options = {image_file_path: "#{Rails.root}/tmp", filename: "output.png"}
46
+ callback_json = "customCallback"
47
+ highchart = PhantomGraph::Convert::Highchart.new(json_str, options, callback_json)
48
+ highchart.result
49
+
50
+ ==== Highstock
51
+ # sample script: spec/phantom_graph/convert/higstock_spec.rb
52
+ options = {image_file_path: "/path/project/public", filename: "report.pdf"}
53
+ highstock = PhantomGraph::Convert::Highstock.new(json_str, options, callback_json)
54
+ highstock.result
55
+
56
+ ==== Outputs: PDF, SVG, PNG, JPG
57
+
58
+ ===== Default options for Highstock and Highchart:
59
+ {width: 1200,
60
+ scale: 0.5,
61
+ constr: "Chart",
62
+ json_file_path: "/tmp",
63
+ image_file_path: "/tmp",
64
+ filename: nil,
65
+ callback_file_path: "/tmp"
66
+ }
67
+
68
+
69
+ = TODO
70
+ 1. Add Google Chart Module
71
+ 2. Add Custom Theme Support
72
+ 3. Add Synchronous Processor
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'PhantomGraph'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
28
+ require 'rake/testtask'
29
+
30
+ Rake::TestTask.new(:test) do |t|
31
+ t.libs << 'lib'
32
+ t.libs << 'test'
33
+ t.pattern = 'test/**/*_test.rb'
34
+ t.verbose = false
35
+ end
36
+
37
+
38
+ task :default => :test
@@ -0,0 +1,7 @@
1
+ require 'logger'
2
+ require 'json'
3
+ require 'phantom_graph/version'
4
+ require 'phantom_graph/base'
5
+ require 'phantom_graph/setting'
6
+ require 'phantom_graph/error'
7
+ require 'phantom_graph/convert'
@@ -0,0 +1,7 @@
1
+ module PhantomGraph
2
+ class Base
3
+ def self.attributes(*names)
4
+ attr_accessor(*names)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ module PhantomGraph
2
+ module Convert
3
+ autoload :Highchart, "phantom_graph/convert/highchart"
4
+ autoload :Stockchart, "phantom_graph/convert/stockchart"
5
+ end
6
+ end
@@ -0,0 +1,107 @@
1
+ module PhantomGraph
2
+ module Convert
3
+ class Highchart < PhantomGraph::Base
4
+ CH_OPTIONS = {width: 600,
5
+ scale: 1,
6
+ constr: "Chart",
7
+ filename: nil,
8
+ json_file_path: "/tmp",
9
+ image_file_path: "/tmp",
10
+ callback_file_path: "/tmp"}
11
+ attributes :callback_file, :json_file, :image_file, :json
12
+
13
+ def initialize( js_json, opts = {}, callback_json = nil )
14
+ options.merge!(PhantomGraph.setting.default_options.merge(opts))
15
+ prepare_tmp_files
16
+ flush_callback(callback_json) if callback_json
17
+ flush_json(js_json)
18
+ end
19
+
20
+ def options
21
+ @options ||= CH_OPTIONS
22
+ end
23
+
24
+ def image
25
+ f = File.new([options[:image_file_path], random_filename].join("/"), "w+")
26
+ f.write(self.image_file.read)
27
+ f.close
28
+ f
29
+ end
30
+
31
+ def result
32
+ image
33
+ end
34
+
35
+ def random_filename
36
+ return @options[:filename] if @options[:filename]
37
+ "#{rand(100000)}-#{Time.now.to_i}.png"
38
+ end
39
+
40
+ def process
41
+ log(to_s)
42
+ log(`#{build_cmd}`)
43
+ end
44
+
45
+ def logger
46
+ @logger ||= ::Logger.new(STDOUT)
47
+ end
48
+
49
+ def flush_json(js_json)
50
+ self.json = js_json
51
+ json_file.write(js_json)
52
+ json_file.flush
53
+ process if options[:auto_process]
54
+ end
55
+
56
+ def flush_callback(callback_json)
57
+ callback_file.write("function(chart) {\n#{callback_json}\n}")
58
+ callback_file.flush
59
+ end
60
+
61
+ def to_s
62
+ "<ImageHighchart path='#{options[:phantom_js_path]}' " +
63
+ "highcharts_convert_path='#{options[:highcharts_convert_path]}' " +
64
+ "config_temp='#{json_file.path}' image_temp='#{image_file.path}' " +
65
+ "phantom_js_command='#{build_cmd}'\njson: #{json.inspect}\n>"
66
+ end
67
+
68
+ def build_cmd
69
+ [:phantom_js_path, :json_file, :image_file].each do |key|
70
+ check_error(key)
71
+ end
72
+ cmd = "#{options[:phantom_js_path]} #{options[:highcharts_convert_path]} "
73
+ cmd += "-infile #{json_file.path} -outfile #{image_file.path} "
74
+ cmd += "-scale #{options[:scale]} " if options[:scale]
75
+ cmd += "-width #{options[:width]} " if options[:width]
76
+ cmd += "-width #{options[:height]} " if options[:height]
77
+ cmd += "-constr #{options[:constr]}" if options[:constr]
78
+ cmd += " -theme #{options[:highcharts_theme_path]}" if options[:highcharts_theme_path]
79
+ cmd
80
+ end
81
+
82
+ def check_error(filekey)
83
+ if filekey == :phantom_js_path
84
+ raise PhantomGraph::Error::NoExecutable.new unless File.exists?( options[filekey].to_s )
85
+ else
86
+ raise PhantomGraph::Error::InvalidSource.new(filekey) unless send(filekey)
87
+ end
88
+ end
89
+
90
+ def prepare_tmp_files
91
+ self.json_file = Tempfile.new( ['json', '.json'], options[:json_file_path] )
92
+ self.callback_file = Tempfile.new( ['callback', '.json'], options[:callback_file_path] )
93
+ self.image_file = Tempfile.new( ['chart', file_ext], options[:image_file_path] )
94
+ end
95
+
96
+ def log(msg)
97
+ logger.debug(msg) if options[:logger]
98
+ end
99
+
100
+ def file_ext
101
+ options[:filename] ? options[:filename].match(/\.\w+$/i).to_s.downcase : ".png"
102
+ end
103
+
104
+
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,11 @@
1
+ module PhantomGraph
2
+ module Convert
3
+ class Stockchart < PhantomGraph::Convert::Highchart
4
+
5
+ def options
6
+ @options ||= CH_OPTIONS.merge(constr: "StockChart")
7
+ end
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module PhantomGraph
2
+ module Error
3
+
4
+ class NoExecutable < StandardError
5
+ def initialize
6
+ msg = "No phantomjs executable found at #{PhantomGraph.setting.phantomjs}\n"
7
+ msg << ">> Please install phantomjs - http://phantomjs.org/download.html"
8
+ super(msg)
9
+ end
10
+ end
11
+
12
+ class InvalidSource < StandardError
13
+ def initialize(msg = nil)
14
+ super("Invalid Source: #{msg}")
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ /*
2
+ Data plugin for Highcharts
3
+
4
+ (c) 2012-2013 Torstein Hønsi
5
+ Last revision 2012-11-27
6
+
7
+ License: www.highcharts.com/license
8
+ */
9
+ (function(f){var k=f.each,n=function(a){this.init(a)};f.extend(n.prototype,{init:function(a){this.options=a;this.columns=a.columns||this.rowsToColumns(a.rows)||[];this.columns.length?this.dataFound():(this.parseCSV(),this.parseTable(),this.parseGoogleSpreadsheet())},dataFound:function(){this.parseTypes();this.findHeaderRow();this.parsed();this.complete()},parseCSV:function(){var a=this,b=this.options,c=b.csv,d=this.columns,e=b.startRow||0,g=b.endRow||Number.MAX_VALUE,h=b.startColumn||0,l=b.endColumn||
10
+ Number.MAX_VALUE,q=0;c&&(c=c.replace(/\r\n/g,"\n").replace(/\r/g,"\n").split(b.lineDelimiter||"\n"),k(c,function(c,m){var o=a.trim(c),f=o.indexOf("#")===0;m>=e&&m<=g&&!f&&o!==""&&(o=c.split(b.itemDelimiter||","),k(o,function(b,a){a>=h&&a<=l&&(d[a-h]||(d[a-h]=[]),d[a-h][q]=b)}),q+=1)}),this.dataFound())},parseTable:function(){var a=this.options,b=a.table,c=this.columns,d=a.startRow||0,e=a.endRow||Number.MAX_VALUE,g=a.startColumn||0,h=a.endColumn||Number.MAX_VALUE,l;b&&(typeof b==="string"&&(b=document.getElementById(b)),
11
+ k(b.getElementsByTagName("tr"),function(a,b){l=0;b>=d&&b<=e&&k(a.childNodes,function(a){if((a.tagName==="TD"||a.tagName==="TH")&&l>=g&&l<=h)c[l]||(c[l]=[]),c[l][b-d]=a.innerHTML,l+=1})}),this.dataFound())},parseGoogleSpreadsheet:function(){var a=this,b=this.options,c=b.googleSpreadsheetKey,d=this.columns,e=b.startRow||0,g=b.endRow||Number.MAX_VALUE,h=b.startColumn||0,l=b.endColumn||Number.MAX_VALUE,f,j;c&&jQuery.getJSON("https://spreadsheets.google.com/feeds/cells/"+c+"/"+(b.googleSpreadsheetWorksheet||
12
+ "od6")+"/public/values?alt=json-in-script&callback=?",function(b){var b=b.feed.entry,c,k=b.length,n=0,p=0,i;for(i=0;i<k;i++)c=b[i],n=Math.max(n,c.gs$cell.col),p=Math.max(p,c.gs$cell.row);for(i=0;i<n;i++)if(i>=h&&i<=l)d[i-h]=[],d[i-h].length=Math.min(p,g-e);for(i=0;i<k;i++)if(c=b[i],f=c.gs$cell.row-1,j=c.gs$cell.col-1,j>=h&&j<=l&&f>=e&&f<=g)d[j-h][f-e]=c.content.$t;a.dataFound()})},findHeaderRow:function(){k(this.columns,function(){});this.headerRow=0},trim:function(a){return typeof a==="string"?a.replace(/^\s+|\s+$/g,
13
+ ""):a},parseTypes:function(){for(var a=this.columns,b=a.length,c,d,e,g;b--;)for(c=a[b].length;c--;)d=a[b][c],e=parseFloat(d),g=this.trim(d),g==e?(a[b][c]=e,e>31536E6?a[b].isDatetime=!0:a[b].isNumeric=!0):(d=this.parseDate(d),b===0&&typeof d==="number"&&!isNaN(d)?(a[b][c]=d,a[b].isDatetime=!0):a[b][c]=g===""?null:g)},dateFormats:{"YYYY-mm-dd":{regex:"^([0-9]{4})-([0-9]{2})-([0-9]{2})$",parser:function(a){return Date.UTC(+a[1],a[2]-1,+a[3])}}},parseDate:function(a){var b=this.options.parseDate,c,d,
14
+ e;b&&(c=b(a));if(typeof a==="string")for(d in this.dateFormats)b=this.dateFormats[d],(e=a.match(b.regex))&&(c=b.parser(e));return c},rowsToColumns:function(a){var b,c,d,e,g;if(a){g=[];c=a.length;for(b=0;b<c;b++){e=a[b].length;for(d=0;d<e;d++)g[d]||(g[d]=[]),g[d][b]=a[b][d]}}return g},parsed:function(){this.options.parsed&&this.options.parsed.call(this,this.columns)},complete:function(){var a=this.columns,b,c,d,e,g=this.options,h,f,k,j,m;if(g.complete){a.length>1&&(d=a.shift(),this.headerRow===0&&
15
+ d.shift(),(b=d.isNumeric||d.isDatetime)||(c=d),d.isDatetime&&(e="datetime"));h=[];for(j=0;j<a.length;j++){this.headerRow===0&&(k=a[j].shift());f=[];for(m=0;m<a[j].length;m++)f[m]=a[j][m]!==void 0?b?[d[m],a[j][m]]:a[j][m]:null;h[j]={name:k,data:f}}g.complete({xAxis:{categories:c,type:e},series:h})}}});f.Data=n;f.data=function(a){return new n(a)};f.wrap(f.Chart.prototype,"init",function(a,b,c){var d=this;b&&b.data?f.data(f.extend(b.data,{complete:function(e){b.series&&k(b.series,function(a,c){b.series[c]=
16
+ f.merge(a,e.series[c])});b=f.merge(e,b);a.call(d,b,c)}})):a.call(d,b,c)})})(Highcharts);
@@ -0,0 +1,257 @@
1
+ /**
2
+ * Gray theme for Highcharts JS
3
+ * @author Torstein Hønsi
4
+ */
5
+
6
+ Highcharts.theme = {
7
+ colors: ["#DDDF0D", "#7798BF", "#55BF3B", "#DF5353", "#aaeeee", "#ff0066", "#eeaaee",
8
+ "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
9
+ chart: {
10
+ backgroundColor: {
11
+ linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
12
+ stops: [
13
+ [0, 'rgb(96, 96, 96)'],
14
+ [1, 'rgb(16, 16, 16)']
15
+ ]
16
+ },
17
+ borderWidth: 0,
18
+ borderRadius: 15,
19
+ plotBackgroundColor: null,
20
+ plotShadow: false,
21
+ plotBorderWidth: 0
22
+ },
23
+ title: {
24
+ style: {
25
+ color: '#FFF',
26
+ font: '16px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
27
+ }
28
+ },
29
+ subtitle: {
30
+ style: {
31
+ color: '#DDD',
32
+ font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
33
+ }
34
+ },
35
+ xAxis: {
36
+ gridLineWidth: 0,
37
+ lineColor: '#999',
38
+ tickColor: '#999',
39
+ labels: {
40
+ style: {
41
+ color: '#999',
42
+ fontWeight: 'bold'
43
+ }
44
+ },
45
+ title: {
46
+ style: {
47
+ color: '#AAA',
48
+ font: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
49
+ }
50
+ }
51
+ },
52
+ yAxis: {
53
+ alternateGridColor: null,
54
+ minorTickInterval: null,
55
+ gridLineColor: 'rgba(255, 255, 255, .1)',
56
+ minorGridLineColor: 'rgba(255,255,255,0.07)',
57
+ lineWidth: 0,
58
+ tickWidth: 0,
59
+ labels: {
60
+ style: {
61
+ color: '#999',
62
+ fontWeight: 'bold'
63
+ }
64
+ },
65
+ title: {
66
+ style: {
67
+ color: '#AAA',
68
+ font: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
69
+ }
70
+ }
71
+ },
72
+ legend: {
73
+ itemStyle: {
74
+ color: '#CCC'
75
+ },
76
+ itemHoverStyle: {
77
+ color: '#FFF'
78
+ },
79
+ itemHiddenStyle: {
80
+ color: '#333'
81
+ }
82
+ },
83
+ labels: {
84
+ style: {
85
+ color: '#CCC'
86
+ }
87
+ },
88
+ tooltip: {
89
+ backgroundColor: {
90
+ linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
91
+ stops: [
92
+ [0, 'rgba(96, 96, 96, .8)'],
93
+ [1, 'rgba(16, 16, 16, .8)']
94
+ ]
95
+ },
96
+ borderWidth: 0,
97
+ style: {
98
+ color: '#FFF'
99
+ }
100
+ },
101
+
102
+
103
+ plotOptions: {
104
+ series: {
105
+ shadow: true
106
+ },
107
+ line: {
108
+ dataLabels: {
109
+ color: '#CCC'
110
+ },
111
+ marker: {
112
+ lineColor: '#333'
113
+ }
114
+ },
115
+ spline: {
116
+ marker: {
117
+ lineColor: '#333'
118
+ }
119
+ },
120
+ scatter: {
121
+ marker: {
122
+ lineColor: '#333'
123
+ }
124
+ },
125
+ candlestick: {
126
+ lineColor: 'white'
127
+ }
128
+ },
129
+
130
+ toolbar: {
131
+ itemStyle: {
132
+ color: '#CCC'
133
+ }
134
+ },
135
+
136
+ navigation: {
137
+ buttonOptions: {
138
+ symbolStroke: '#DDDDDD',
139
+ hoverSymbolStroke: '#FFFFFF',
140
+ theme: {
141
+ fill: {
142
+ linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
143
+ stops: [
144
+ [0.4, '#606060'],
145
+ [0.6, '#333333']
146
+ ]
147
+ },
148
+ stroke: '#000000'
149
+ }
150
+ }
151
+ },
152
+
153
+ // scroll charts
154
+ rangeSelector: {
155
+ buttonTheme: {
156
+ fill: {
157
+ linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
158
+ stops: [
159
+ [0.4, '#888'],
160
+ [0.6, '#555']
161
+ ]
162
+ },
163
+ stroke: '#000000',
164
+ style: {
165
+ color: '#CCC',
166
+ fontWeight: 'bold'
167
+ },
168
+ states: {
169
+ hover: {
170
+ fill: {
171
+ linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
172
+ stops: [
173
+ [0.4, '#BBB'],
174
+ [0.6, '#888']
175
+ ]
176
+ },
177
+ stroke: '#000000',
178
+ style: {
179
+ color: 'white'
180
+ }
181
+ },
182
+ select: {
183
+ fill: {
184
+ linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
185
+ stops: [
186
+ [0.1, '#000'],
187
+ [0.3, '#333']
188
+ ]
189
+ },
190
+ stroke: '#000000',
191
+ style: {
192
+ color: 'yellow'
193
+ }
194
+ }
195
+ }
196
+ },
197
+ inputStyle: {
198
+ backgroundColor: '#333',
199
+ color: 'silver'
200
+ },
201
+ labelStyle: {
202
+ color: 'silver'
203
+ }
204
+ },
205
+
206
+ navigator: {
207
+ handles: {
208
+ backgroundColor: '#666',
209
+ borderColor: '#AAA'
210
+ },
211
+ outlineColor: '#CCC',
212
+ maskFill: 'rgba(16, 16, 16, 0.5)',
213
+ series: {
214
+ color: '#7798BF',
215
+ lineColor: '#A6C7ED'
216
+ }
217
+ },
218
+
219
+ scrollbar: {
220
+ barBackgroundColor: {
221
+ linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
222
+ stops: [
223
+ [0.4, '#888'],
224
+ [0.6, '#555']
225
+ ]
226
+ },
227
+ barBorderColor: '#CCC',
228
+ buttonArrowColor: '#CCC',
229
+ buttonBackgroundColor: {
230
+ linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
231
+ stops: [
232
+ [0.4, '#888'],
233
+ [0.6, '#555']
234
+ ]
235
+ },
236
+ buttonBorderColor: '#CCC',
237
+ rifleColor: '#FFF',
238
+ trackBackgroundColor: {
239
+ linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
240
+ stops: [
241
+ [0, '#000'],
242
+ [1, '#333']
243
+ ]
244
+ },
245
+ trackBorderColor: '#666'
246
+ },
247
+
248
+ // special colors for some of the demo examples
249
+ legendBackgroundColor: 'rgba(48, 48, 48, 0.8)',
250
+ legendBackgroundColorSolid: 'rgb(70, 70, 70)',
251
+ dataLabelsColor: '#444',
252
+ textColor: '#E0E0E0',
253
+ maskColor: 'rgba(255,255,255,0.3)'
254
+ };
255
+
256
+ // Apply the theme
257
+ var highchartsOptions = Highcharts.setOptions(Highcharts.theme);