diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..a6b8dc8
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,6 @@
+include MANIFEST.in
+include LICENSE
+
+graft tests
+
+global-exclude *.py[co]
diff --git a/README.md b/README.md
index 3a4aa28..c57b75b 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# python-highcharts
+# python-highcharts [](https://circleci.com/gh/kyper-data/python-highcharts)
## License
@@ -10,13 +10,16 @@ However, please be aware that the Highcharts project itself, as well as Highmaps
python-highcharts is a simple translation layer between Python and Javascript for Highcharts projects (highcharts, highmaps, and highstocks).
-In addition, python-highcharts integrates with [Jupyter/IPython notebook](https://github.com/jupyter/notebook), which enables you to render Highcharts, Highmaps, and Highstock visualizations directly in notebooks. See examples [here](https://github.com/kyper-data/python-highcharts/tree/developer/examples/ipynb).
+In addition, python-highcharts integrates with [Jupyter notebook](https://github.com/jupyter/notebook), which enables you to render Highcharts, Highmaps, and Highstock visualizations directly in notebooks. See examples [here](https://github.com/kyper-data/python-highcharts/tree/developer/examples/ipynb).
The original framework was inspired by [python-nvd3](https://github.com/areski/python-nvd3) and [PyHighcharts](https://github.com/fidyeates/PyHighcharts).
## Installation
--need to work on this-
+python-highcharts supports Python 2.7/3.4+ and is available on PyPI. To install:
+```
+pip install python-highcharts
+```
---------------------------------------------------------------------------------------------------------------
# Highcharts/Highstock
@@ -193,6 +196,12 @@ chart.add_data_set(data, 'spline', 'Temperature', marker={'enabled': False})
chart
```
+### Example notebooks:
+
+* [Highcharts](http://nbviewer.ipython.org/github/kyper-data/python-highcharts/blob/master/examples/ipynb/highcharts/Example1.ipynb)
+* [Highmaps](http://nbviewer.ipython.org/github/kyper-data/python-highcharts/blob/master/examples/ipynb/highmaps/Example1.ipynb)
+* [Highstock](http://nbviewer.ipython.org/github/kyper-data/python-highcharts/blob/master/examples/ipynb/highstock/Example1-basic-line.ipynb)
+
## Todo:
* More charts support
@@ -581,4 +590,4 @@ chart.save_file()
* More examples
* Clean code and put more explanation
-Reference: [Highcharts API](http://api.highcharts.com/highcharts)
\ No newline at end of file
+Reference: [Highcharts API](http://api.highcharts.com/highcharts)
diff --git a/examples/highcharts/heatmap.py b/examples/highcharts/heatmap.py
new file mode 100644
index 0000000..338134b
--- /dev/null
+++ b/examples/highcharts/heatmap.py
@@ -0,0 +1,107 @@
+# -*- coding: utf-8 -*-
+"""
+Highcharts Demos
+Heatmap: http://www.highcharts.com/demo/heatmap
+"""
+from highcharts import Highchart
+H = Highchart()
+
+data = [
+ [0, 0, 10],
+ [0, 1, 19],
+ [0, 2, 8],
+ [0, 3, 24],
+ [0, 4, 67],
+ [1, 0, 92],
+ [1, 1, 58],
+ [1, 2, 78],
+ [1, 3, 117],
+ [1, 4, 48],
+ [2, 0, 35],
+ [2, 1, 15],
+ [2, 2, 123],
+ [2, 3, 64],
+ [2, 4, 52],
+ [3, 0, 72],
+ [3, 1, 132],
+ [3, 2, 114],
+ [3, 3, 19],
+ [3, 4, 16],
+ [4, 0, 38],
+ [4, 1, 5],
+ [4, 2, 8],
+ [4, 3, 117],
+ [4, 4, 115],
+ [5, 0, 88],
+ [5, 1, 32],
+ [5, 2, 12],
+ [5, 3, 6],
+ [5, 4, 120],
+ [6, 0, 13],
+ [6, 1, 44],
+ [6, 2, 88],
+ [6, 3, 98],
+ [6, 4, 96],
+ [7, 0, 31],
+ [7, 1, 1],
+ [7, 2, 82],
+ [7, 3, 32],
+ [7, 4, 30],
+ [8, 0, 85],
+ [8, 1, 97],
+ [8, 2, 123],
+ [8, 3, 64],
+ [8, 4, 84],
+ [9, 0, 47],
+ [9, 1, 114],
+ [9, 2, 31],
+ [9, 3, 48],
+ [9, 4, 91]
+]
+
+H.add_data_set(data, )
+
+H.set_options('chart', {
+ 'type': 'heatmap',
+ 'marginTop': 40,
+ 'marginBottom': 80,
+ 'plotBorderWidth': 1
+})
+
+H.set_options('xAxis', {
+ 'categories':
+ ['Alexander', 'Marie', 'Maximilian', 'Sophia', 'Lukas', 'Maria', 'Leon', 'Anna', 'Tim', 'Laura']
+})
+
+H.set_options('yAxis', {
+ 'categories': ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
+ 'title': None
+})
+
+H.set_options('title', {
+ 'text': "Sales per employee per weekday"
+})
+
+H.set_options('colorAxis', {
+ 'min': 0,
+ 'minColor': '#FFFFFF',
+ 'maxColor': '#7CB5EC'
+})
+
+H.set_options('legend', {
+ 'align': 'right',
+ 'layout': 'vertical',
+ 'margin': 0,
+ 'verticalAlign': 'top',
+ 'y': 25,
+ 'symbolHeight': 280
+})
+
+H.set_options('tooltip', {
+ 'formatter': "function () {" +
+ "return '' + this.series.xAxis.categories[this.point.x] + ' sold
' +" +
+ "this.point.value + ' items on
' + this.series.yAxis.categories[this.point.y] + '';" +
+ "}"
+})
+
+H.htmlcontent
\ No newline at end of file
diff --git a/examples/highcharts/spline-irregular-time.py b/examples/highcharts/spline-irregular-time.py
new file mode 100644
index 0000000..7ad233f
--- /dev/null
+++ b/examples/highcharts/spline-irregular-time.py
@@ -0,0 +1,119 @@
+# -*- coding: utf-8 -*-
+"""
+Highcharts Demos
+Time data with irregular intervals: http://www.highcharts.com/demo/spline-irregular-time
+"""
+from datetime import datetime
+from highcharts import Highchart
+H = Highchart()
+
+winter_12_13_data = [
+ [datetime(1970, 10, 21), 0],
+ [datetime(1970, 11, 4), 0.28],
+ [datetime(1970, 11, 9), 0.25],
+ [datetime(1970, 11, 27), 0.2],
+ [datetime(1970, 12, 2), 0.28],
+ [datetime(1970, 12, 26), 0.28],
+ [datetime(1970, 12, 29), 0.47],
+ [datetime(1971, 1, 11), 0.79],
+ [datetime(1971, 1, 26), 0.72],
+ [datetime(1971, 2, 3), 1.02],
+ [datetime(1971, 2, 11), 1.12],
+ [datetime(1971, 2, 25), 1.2],
+ [datetime(1971, 3, 11), 1.18],
+ [datetime(1971, 4, 11), 1.19],
+ [datetime(1971, 5, 1), 1.85],
+ [datetime(1971, 5, 5), 2.22],
+ [datetime(1971, 5, 19), 1.15],
+ [datetime(1971, 6, 3), 0]
+]
+
+winter_13_14_data = [
+ [datetime(1970, 10, 29), 0],
+ [datetime(1970, 11, 9), 0.4],
+ [datetime(1970, 12, 1), 0.25],
+ [datetime(1971, 1, 1), 1.66],
+ [datetime(1971, 1, 10), 1.8],
+ [datetime(1971, 2, 19), 1.76],
+ [datetime(1971, 3, 25), 2.62],
+ [datetime(1971, 4, 19), 2.41],
+ [datetime(1971, 4, 30), 2.05],
+ [datetime(1971, 5, 14), 1.7],
+ [datetime(1971, 5, 24), 1.1],
+ [datetime(1971, 6, 10), 0]
+]
+
+winter_14_15_data = [
+ [datetime(1970, 11, 25), 0],
+ [datetime(1970, 12, 6), 0.25],
+ [datetime(1970, 12, 20), 1.41],
+ [datetime(1970, 12, 25), 1.64],
+ [datetime(1971, 1, 4), 1.6],
+ [datetime(1971, 1, 17), 2.55],
+ [datetime(1971, 1, 24), 2.62],
+ [datetime(1971, 2, 4), 2.5],
+ [datetime(1971, 2, 14), 2.42],
+ [datetime(1971, 3, 6), 2.74],
+ [datetime(1971, 3, 14), 2.62],
+ [datetime(1971, 3, 24), 2.6],
+ [datetime(1971, 4, 2), 2.81],
+ [datetime(1971, 4, 12), 2.63],
+ [datetime(1971, 4, 28), 2.77],
+ [datetime(1971, 5, 5), 2.68],
+ [datetime(1971, 5, 10), 2.56],
+ [datetime(1971, 5, 15), 2.39],
+ [datetime(1971, 5, 20), 2.3],
+ [datetime(1971, 6, 5), 2],
+ [datetime(1971, 6, 10), 1.85],
+ [datetime(1971, 6, 15), 1.49],
+ [datetime(1971, 6, 23), 1.08]
+]
+
+H.add_data_set(winter_12_13_data, series_type="spline", name="Winter 2012-2013")
+H.add_data_set(winter_13_14_data, series_type="spline", name="Winter 2013-2014")
+H.add_data_set(winter_14_15_data, series_type="spline", name="Winter 2014-2015")
+
+H.set_options('chart', {
+ 'type': 'spline'
+})
+
+H.set_options('xAxis', {
+ 'type': 'datetime',
+ 'dateTimeLabelFormats': { # don't display the dummy year
+ 'month': '%e. %b',
+ 'year': '%b'
+ },
+ 'title': {
+ 'text': 'Date'
+ }
+})
+
+H.set_options('yAxis', {
+ 'title': {
+ 'text': 'Snow depth (m)'
+ },
+ 'min': 0
+})
+
+H.set_options('title', {
+ 'text': "Snow depth at Vikjafjellet, Norway"
+})
+
+H.set_options('subtitle', {
+ 'text': "Irregular time data in Highcharts JS"
+})
+
+H.set_options('tooltip', {
+ 'headerFormat': '{series.name}
',
+ 'pointFormat': '{point.x:%e. %b}: {point.y:.2f} m'
+})
+
+H.set_options('plotOptions', {
+ 'spline': {
+ 'marker': {
+ 'enabled': True
+ }
+ }
+})
+
+H.htmlcontent
\ No newline at end of file
diff --git a/examples/ipynb/highcharts/3d-scatter-draggable.ipynb b/examples/ipynb/highcharts/3d-scatter-draggable.ipynb
index 4f2c9de..cfd6205 100644
--- a/examples/ipynb/highcharts/3d-scatter-draggable.ipynb
+++ b/examples/ipynb/highcharts/3d-scatter-draggable.ipynb
@@ -12,7 +12,7 @@
},
{
"cell_type": "code",
- "execution_count": 8,
+ "execution_count": 1,
"metadata": {
"collapsed": false,
"scrolled": false
@@ -21,7 +21,7 @@
{
"data": {
"text/html": [
- ""
+ "</html> \"height= 400 width =550>"
],
"text/plain": [
- ""
+ ""
]
},
- "execution_count": 8,
+ "execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
diff --git a/examples/ipynb/highcharts/heatmap.ipynb b/examples/ipynb/highcharts/heatmap.ipynb
new file mode 100644
index 0000000..9fd0880
--- /dev/null
+++ b/examples/ipynb/highcharts/heatmap.ipynb
@@ -0,0 +1,159 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# -*- coding: utf-8 -*-\n",
+ "\"\"\"\n",
+ "Highcharts Demos\n",
+ "Heatmap: http://www.highcharts.com/demo/heatmap\n",
+ "\"\"\"\n",
+ "from highcharts import Highchart\n",
+ "H = Highchart()\n",
+ "\n",
+ "data = [\n",
+ " [0, 0, 10],\n",
+ " [0, 1, 19],\n",
+ " [0, 2, 8],\n",
+ " [0, 3, 24],\n",
+ " [0, 4, 67],\n",
+ " [1, 0, 92],\n",
+ " [1, 1, 58],\n",
+ " [1, 2, 78],\n",
+ " [1, 3, 117],\n",
+ " [1, 4, 48],\n",
+ " [2, 0, 35],\n",
+ " [2, 1, 15],\n",
+ " [2, 2, 123],\n",
+ " [2, 3, 64],\n",
+ " [2, 4, 52],\n",
+ " [3, 0, 72],\n",
+ " [3, 1, 132],\n",
+ " [3, 2, 114],\n",
+ " [3, 3, 19],\n",
+ " [3, 4, 16],\n",
+ " [4, 0, 38],\n",
+ " [4, 1, 5],\n",
+ " [4, 2, 8],\n",
+ " [4, 3, 117],\n",
+ " [4, 4, 115],\n",
+ " [5, 0, 88],\n",
+ " [5, 1, 32],\n",
+ " [5, 2, 12],\n",
+ " [5, 3, 6],\n",
+ " [5, 4, 120],\n",
+ " [6, 0, 13],\n",
+ " [6, 1, 44],\n",
+ " [6, 2, 88],\n",
+ " [6, 3, 98],\n",
+ " [6, 4, 96],\n",
+ " [7, 0, 31],\n",
+ " [7, 1, 1],\n",
+ " [7, 2, 82],\n",
+ " [7, 3, 32],\n",
+ " [7, 4, 30],\n",
+ " [8, 0, 85],\n",
+ " [8, 1, 97],\n",
+ " [8, 2, 123],\n",
+ " [8, 3, 64],\n",
+ " [8, 4, 84],\n",
+ " [9, 0, 47],\n",
+ " [9, 1, 114],\n",
+ " [9, 2, 31],\n",
+ " [9, 3, 48],\n",
+ " [9, 4, 91]\n",
+ "]\n",
+ "\n",
+ "H.add_data_set(data, series_type='heatmap', borderWidth=1, dataLabels={\n",
+ " 'enabled': True,\n",
+ " 'color': '#000000'\n",
+ "})\n",
+ "\n",
+ "H.set_options('chart', {\n",
+ " 'type': 'heatmap',\n",
+ " 'marginTop': 40,\n",
+ " 'marginBottom': 80,\n",
+ " 'plotBorderWidth': 1\n",
+ "})\n",
+ "\n",
+ "H.set_options('xAxis', {\n",
+ " 'categories': \n",
+ " ['Alexander', 'Marie', 'Maximilian', 'Sophia', 'Lukas', 'Maria', 'Leon', 'Anna', 'Tim', 'Laura']\n",
+ "})\n",
+ "\n",
+ "H.set_options('yAxis', {\n",
+ " 'categories': ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],\n",
+ " 'title': None\n",
+ "})\n",
+ "\n",
+ "H.set_options('title', {\n",
+ " 'text': \"Sales per employee per weekday\"\n",
+ "})\n",
+ "\n",
+ "H.set_options('colorAxis', {\n",
+ " 'min': 0,\n",
+ " 'minColor': '#FFFFFF',\n",
+ " 'maxColor': '#7CB5EC'\n",
+ "})\n",
+ "\n",
+ "H.set_options('legend', {\n",
+ " 'align': 'right',\n",
+ " 'layout': 'vertical',\n",
+ " 'margin': 0,\n",
+ " 'verticalAlign': 'top',\n",
+ " 'y': 25,\n",
+ " 'symbolHeight': 280\n",
+ "})\n",
+ "\n",
+ "H.set_options('tooltip', {\n",
+ " 'formatter': \"function () {\" + \n",
+ " \"return '' + this.series.xAxis.categories[this.point.x] + ' sold
' +\" +\n",
+ " \"this.point.value + ' items on
' + this.series.yAxis.categories[this.point.y] + '';\" +\n",
+ " \"}\"\n",
+ "})\n",
+ "\n",
+ "H"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.5.1"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 1
+}
diff --git a/examples/ipynb/highcharts/spline-irregular-time.ipynb b/examples/ipynb/highcharts/spline-irregular-time.ipynb
new file mode 100644
index 0000000..0b1139a
--- /dev/null
+++ b/examples/ipynb/highcharts/spline-irregular-time.ipynb
@@ -0,0 +1,168 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# -*- coding: utf-8 -*-\n",
+ "\"\"\"\n",
+ "Highcharts Demos\n",
+ "Time data with irregular intervals: http://www.highcharts.com/demo/spline-irregular-time\n",
+ "\"\"\"\n",
+ "from datetime import datetime\n",
+ "from highcharts import Highchart\n",
+ "H = Highchart()\n",
+ "\n",
+ "winter_12_13_data = [\n",
+ " [datetime(1970, 10, 21), 0],\n",
+ " [datetime(1970, 11, 4), 0.28],\n",
+ " [datetime(1970, 11, 9), 0.25],\n",
+ " [datetime(1970, 11, 27), 0.2],\n",
+ " [datetime(1970, 12, 2), 0.28],\n",
+ " [datetime(1970, 12, 26), 0.28],\n",
+ " [datetime(1970, 12, 29), 0.47],\n",
+ " [datetime(1971, 1, 11), 0.79],\n",
+ " [datetime(1971, 1, 26), 0.72],\n",
+ " [datetime(1971, 2, 3), 1.02],\n",
+ " [datetime(1971, 2, 11), 1.12],\n",
+ " [datetime(1971, 2, 25), 1.2],\n",
+ " [datetime(1971, 3, 11), 1.18],\n",
+ " [datetime(1971, 4, 11), 1.19],\n",
+ " [datetime(1971, 5, 1), 1.85],\n",
+ " [datetime(1971, 5, 5), 2.22],\n",
+ " [datetime(1971, 5, 19), 1.15],\n",
+ " [datetime(1971, 6, 3), 0]\n",
+ "]\n",
+ "\n",
+ "winter_13_14_data = [\n",
+ " [datetime(1970, 10, 29), 0],\n",
+ " [datetime(1970, 11, 9), 0.4],\n",
+ " [datetime(1970, 12, 1), 0.25],\n",
+ " [datetime(1971, 1, 1), 1.66],\n",
+ " [datetime(1971, 1, 10), 1.8],\n",
+ " [datetime(1971, 2, 19), 1.76],\n",
+ " [datetime(1971, 3, 25), 2.62],\n",
+ " [datetime(1971, 4, 19), 2.41],\n",
+ " [datetime(1971, 4, 30), 2.05],\n",
+ " [datetime(1971, 5, 14), 1.7],\n",
+ " [datetime(1971, 5, 24), 1.1],\n",
+ " [datetime(1971, 6, 10), 0]\n",
+ "]\n",
+ "\n",
+ "winter_14_15_data = [\n",
+ " [datetime(1970, 11, 25), 0],\n",
+ " [datetime(1970, 12, 6), 0.25],\n",
+ " [datetime(1970, 12, 20), 1.41],\n",
+ " [datetime(1970, 12, 25), 1.64],\n",
+ " [datetime(1971, 1, 4), 1.6],\n",
+ " [datetime(1971, 1, 17), 2.55],\n",
+ " [datetime(1971, 1, 24), 2.62],\n",
+ " [datetime(1971, 2, 4), 2.5],\n",
+ " [datetime(1971, 2, 14), 2.42],\n",
+ " [datetime(1971, 3, 6), 2.74],\n",
+ " [datetime(1971, 3, 14), 2.62],\n",
+ " [datetime(1971, 3, 24), 2.6],\n",
+ " [datetime(1971, 4, 2), 2.81],\n",
+ " [datetime(1971, 4, 12), 2.63],\n",
+ " [datetime(1971, 4, 28), 2.77],\n",
+ " [datetime(1971, 5, 5), 2.68],\n",
+ " [datetime(1971, 5, 10), 2.56],\n",
+ " [datetime(1971, 5, 15), 2.39],\n",
+ " [datetime(1971, 5, 20), 2.3],\n",
+ " [datetime(1971, 6, 5), 2],\n",
+ " [datetime(1971, 6, 10), 1.85],\n",
+ " [datetime(1971, 6, 15), 1.49],\n",
+ " [datetime(1971, 6, 23), 1.08]\n",
+ "]\n",
+ "\n",
+ "H.add_data_set(winter_12_13_data, series_type=\"spline\", name=\"Winter 2012-2013\")\n",
+ "H.add_data_set(winter_13_14_data, series_type=\"spline\", name=\"Winter 2013-2014\")\n",
+ "H.add_data_set(winter_14_15_data, series_type=\"spline\", name=\"Winter 2014-2015\")\n",
+ "\n",
+ "H.set_options('chart', {\n",
+ " 'type': 'spline'\n",
+ "})\n",
+ "\n",
+ "H.set_options('xAxis', {\n",
+ " 'type': 'datetime',\n",
+ " 'dateTimeLabelFormats': { # don't display the dummy year\n",
+ " 'month': '%e. %b',\n",
+ " 'year': '%b'\n",
+ " },\n",
+ " 'title': {\n",
+ " 'text': 'Date'\n",
+ " }\n",
+ "})\n",
+ "\n",
+ "H.set_options('yAxis', {\n",
+ " 'title': {\n",
+ " 'text': 'Snow depth (m)'\n",
+ " },\n",
+ " 'min': 0\n",
+ "})\n",
+ "\n",
+ "H.set_options('title', {\n",
+ " 'text': \"Snow depth at Vikjafjellet, Norway\"\n",
+ "})\n",
+ "\n",
+ "H.set_options('subtitle', {\n",
+ " 'text': \"Irregular time data in Highcharts JS\"\n",
+ "})\n",
+ "\n",
+ "H.set_options('tooltip', {\n",
+ " 'headerFormat': '{series.name}
',\n",
+ " 'pointFormat': '{point.x:%e. %b}: {point.y:.2f} m'\n",
+ "})\n",
+ "\n",
+ "H.set_options('plotOptions', {\n",
+ " 'spline': {\n",
+ " 'marker': {\n",
+ " 'enabled': True\n",
+ " }\n",
+ " }\n",
+ "})\n",
+ "\n",
+ "H"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.5.1"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 1
+}
diff --git a/highcharts/highcharts/common.py b/highcharts/highcharts/common.py
index fe780ba..ab929fe 100644
--- a/highcharts/highcharts/common.py
+++ b/highcharts/highcharts/common.py
@@ -371,7 +371,7 @@ class Events(CommonObject):
class Point(CommonObject):
ALLOWED_OPTIONS = {
- "events": Events
+ "events": (Events, dict)
}
class Position(CommonObject):
@@ -568,6 +568,7 @@ class Hover(CommonObject):
"marker": (Marker, dict),
"radius": int,
"radiusPlus": int,
+ "color": (ColorObject, basestring, dict),
}
class States(CommonObject):
@@ -661,7 +662,7 @@ class PlotBands(ArrayObject):
class PlotLines(ArrayObject):
ALLOWED_OPTIONS = {
"color": (ColorObject, basestring, dict),
- "dashStyle": int,
+ "dashStyle": basestring,
"events": (Events, dict),
"id": basestring,
"label": (Labels, dict),
@@ -695,6 +696,14 @@ class Breaks(ArrayObject):
"to": [int, float],
}
+class DataClasses(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "color": (ColorObject, basestring, dict),
+ "from": [int, float],
+ "name": basestring,
+ "to": [int, float],
+ }
+
class Zones(ArrayObject):
ALLOWED_OPTIONS = {
"color": (ColorObject, basestring, dict),
diff --git a/highcharts/highcharts/highchart_types.py b/highcharts/highcharts/highchart_types.py
index 09817af..c8c241d 100644
--- a/highcharts/highcharts/highchart_types.py
+++ b/highcharts/highcharts/highchart_types.py
@@ -429,6 +429,7 @@
"cropThreshold": int,
"dashStyle": basestring,
"lineWidth": int,
+ "linkedTo": basestring,
"marker": (Marker, dict),
"pointInterval": int,
"pointPlacement": [basestring, int, float],
@@ -479,6 +480,7 @@
"selected": bool,
"sliced": bool,
"showInLegend": bool,
+ "stack": basestring,
"type": basestring,
"visible": bool,
"x": [int, float],
@@ -617,26 +619,27 @@ def __getattr__(self,item):
class Series(object):
"""Series class for input data """
- def __init__(self,data,series_type="line",supress_errors=False,**kwargs):
+ def __init__(self, data, series_type="line", supress_errors=False, **kwargs):
# List of dictionaries. Each dict contains data and properties,
# which need to handle before construct the object for series
- for item in data:
- if isinstance(item, dict):
- for k, v in item.items():
- if k in DATA_SERIES_ALLOWED_OPTIONS:
- if SeriesOptions.__validate_options__(k,v,DATA_SERIES_ALLOWED_OPTIONS[k]):
- if isinstance(DATA_SERIES_ALLOWED_OPTIONS[k], tuple):
- if isinstance(v, dict):
- item.update({k:DATA_SERIES_ALLOWED_OPTIONS[k][0](**v)})
- elif isinstance(v, CommonObject) or isinstance(v, ArrayObject) or \
- isinstance(v, CSSObject) or isinstance(v, SVGObject) or isinstance(v, ColorObject) or \
- isinstance(v, JSfunction) or isinstance(v, Formatter) or isinstance(v, datetime.datetime):
- item.update({k:v})
+ if isinstance(data, list):
+ for item in data:
+ if isinstance(item, dict):
+ for k, v in item.items():
+ if k in DATA_SERIES_ALLOWED_OPTIONS:
+ if SeriesOptions.__validate_options__(k,v,DATA_SERIES_ALLOWED_OPTIONS[k]):
+ if isinstance(DATA_SERIES_ALLOWED_OPTIONS[k], tuple):
+ if isinstance(v, dict):
+ item.update({k:DATA_SERIES_ALLOWED_OPTIONS[k][0](**v)})
+ elif isinstance(v, CommonObject) or isinstance(v, ArrayObject) or \
+ isinstance(v, CSSObject) or isinstance(v, SVGObject) or isinstance(v, ColorObject) or \
+ isinstance(v, JSfunction) or isinstance(v, Formatter) or isinstance(v, datetime.datetime):
+ item.update({k:v})
+ else:
+ item.update({k:DATA_SERIES_ALLOWED_OPTIONS[k][0](v)})
else:
- item.update({k:DATA_SERIES_ALLOWED_OPTIONS[k][0](v)})
- else:
- item.update({k:v})
+ item.update({k:v})
self.__dict__.update({
"data": data,
diff --git a/highcharts/highcharts/highcharts.py b/highcharts/highcharts/highcharts.py
index 86f38b1..59e093e 100644
--- a/highcharts/highcharts/highcharts.py
+++ b/highcharts/highcharts/highcharts.py
@@ -6,14 +6,14 @@
from past.builtins import basestring
from jinja2 import Environment, PackageLoader
-# import sys
-# reload(sys)
-# sys.setdefaultencoding("utf-8")
import json, uuid
-import datetime, random, os, inspect
+import re
+import datetime
+import urllib.request, urllib.error, urllib.parse
+import html
from collections import Iterable
-from .options import BaseOptions, ChartOptions, \
+from .options import BaseOptions, ChartOptions, ColorAxisOptions, \
ColorsOptions, CreditsOptions, DrilldownOptions, ExportingOptions, \
GlobalOptions, LabelsOptions, LangOptions, \
LegendOptions, LoadingOptions, NavigationOptions, PaneOptions, \
@@ -52,6 +52,9 @@ def __init__(self, **kwargs):
This is the base class for all the charts. The following keywords are
accepted:
:keyword: **display_container** - default: ``True``
+ **offline - default: ``False``
+ If True, download all .js and .css file and put them
+ into the generated .html so it can be viewed offline.
"""
# set the model
self.model = self.__class__.__name__ #: The chart model,
@@ -60,13 +63,15 @@ def __init__(self, **kwargs):
# an Instance of Jinja2 template
self.template_page_highcharts = template_page
self.template_content_highcharts = template_content
+
# set Javascript src, Highcharts lib needs to make sure it's up to date
self.JSsource = [
- 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js',
- 'https://code.highcharts.com/highcharts.js',
- 'https://code.highcharts.com/highcharts-more.js',
- 'https://code.highcharts.com/modules/exporting.js'
+ 'https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js',
+ 'https://code.highcharts.com/6/highcharts.js',
+ 'https://code.highcharts.com/6/highcharts-more.js',
+ 'https://code.highcharts.com/6/modules/heatmap.js',
+ 'https://code.highcharts.com/6/modules/exporting.js'
]
# set CSS src
@@ -74,16 +79,20 @@ def __init__(self, **kwargs):
'https://www.highcharts.com/highslide/highslide.css',
]
+
+ self.offline = kwargs.get("offline", False)
+
# set data
self.data = []
self.data_temp = []
# Data from jsonp
self.jsonp_data_flag = False
+ self.jsonp_data_url_list = [] # DEM 2017/07/27: List of JSON data sources
# set drilldown data
self.drilldown_data = []
self.drilldown_data_temp = []
-
+
# javascript
self.jscript_head_flag = False
self.jscript_head = kwargs.get('jscript_head', None)
@@ -110,6 +119,7 @@ def __init__(self, **kwargs):
# Bind Base Classes to self
self.options = {
"chart": ChartOptions(),
+ #"colorAxis" : ColorAxisOptions(),
"colors": ColorsOptions(),
"credits": CreditsOptions(),
#"data": #NotImplemented
@@ -211,10 +221,10 @@ def add_drilldown_data_set(self, data, series_type, id, **kwargs):
self.drilldown_data_set_count += 1
if self.drilldown_flag == False:
self.drilldown_flag = True
-
+
kwargs.update({'id':id})
series_data = Series(data, series_type=series_type, **kwargs)
-
+
series_data.__options__().update(SeriesOptions(series_type=series_type, **kwargs).__options__())
self.drilldown_data_temp.append(series_data)
@@ -224,12 +234,17 @@ def add_data_from_jsonp(self, data_src, data_name='json_data', series_type="line
the data_src is the https link for data
and it must be in jsonp format
"""
- self.jsonp_data_flag = True
- self.jsonp_data_url = json.dumps(data_src)
- if data_name == 'data':
- data_name = 'json_'+ data_name
- self.jsonp_data = data_name
+ if not self.jsonp_data_flag:
+ self.jsonp_data_flag = True
+
+ if data_name == 'data':
+ data_name = 'json_'+ data_name
+
+ self.jsonp_data = data_name
self.add_data_set(RawJavaScriptText(data_name), series_type, name=name, **kwargs)
+ # DEM 2017/07/27: Append new JSON data source to a list instead of
+ # replacing whatever already exists
+ self.jsonp_data_url_list.append(json.dumps(data_src))
def add_JSscript(self, js_script, js_loc):
@@ -264,10 +279,14 @@ def set_options(self, option_type, option_dict, force_options=False):
self.options[option_type].update(**each_dict)
elif option_type == 'colors':
self.options["colors"].set_colors(option_dict) # option_dict should be a list
-
elif option_type == 'zAxis':
self.options.update({'zAxis': zAxisOptions()})
self.options[option_type].update_dict(**option_dict)
+ elif option_type in ["global" , "lang"]: #Highcharts.setOptions:
+ self.setOptions[option_type].update_dict(**option_dict)
+ elif option_type == 'colorAxis':
+ self.options.update({'colorAxis': ColorAxisOptions()})
+ self.options[option_type].update_dict(**option_dict)
else:
self.options[option_type].update_dict(**option_dict)
@@ -292,9 +311,14 @@ def buildcontent(self):
self.buildcontainer()
self.option = json.dumps(self.options, cls = HighchartsEncoder)
- self.setoption = json.dumps(self.setOptions, cls = HighchartsEncoder)
+ self.setoption = json.dumps(self.setOptions, cls = HighchartsEncoder)
self.data = json.dumps(self.data_temp, cls = HighchartsEncoder)
-
+
+ # DEM 2017/04/25: Make 'data' available as an array
+ # ... this permits jinja2 array access to each data definition
+ # ... which is useful for looping over multiple data sources
+ self.data_list = [json.dumps(x, cls = HighchartsEncoder) for x in self.data_temp]
+
if self.drilldown_flag:
self.drilldown_data = json.dumps(self.drilldown_data_temp, cls = HighchartsEncoder)
self._htmlcontent = self.template_content_highcharts.render(chart=self).encode('utf-8')
@@ -318,13 +342,27 @@ def buildhtmlheader(self):
if self.drilldown_flag:
self.add_JSsource('http://code.highcharts.com/modules/drilldown.js')
- self.header_css = [
- '' % h for h in self.CSSsource
- ]
- self.header_js = [
- '' % h for h in self.JSsource
- ]
+
+ if self.offline:
+ opener = urllib.request.build_opener()
+ opener.addheaders = [('User-Agent', 'Mozilla/5.0')]
+
+ self.header_css = [
+ '' % opener.open(h).read() for h in self.CSSsource
+ ]
+
+ self.header_js = [
+ '' % opener.open(h).read() for h in self.JSsource
+ ]
+ else:
+ self.header_css = [
+ '' % h for h in self.CSSsource
+ ]
+
+ self.header_js = [
+ '' % h for h in self.JSsource
+ ]
self.htmlheader = ''
for css in self.header_css:
@@ -357,6 +395,24 @@ def buildcontainer(self):
def htmlcontent(self):
return self.buildhtml()
+ @property
+ def iframe(self):
+ htmlsrcdoc = html.escape(self.htmlcontent)
+ htmlsrcdoc = re.sub('\\n', ' ', htmlsrcdoc)
+ htmlsrcdoc = re.sub(' +', ' ', htmlsrcdoc)
+ width = int(self.options['chart'].__dict__['width']) if self.options['chart'].__dict__.get('width') else 820
+ height = int(self.options['chart'].__dict__['height']) if self.options['chart'].__dict__.get('height') else 520
+
+ if self.options['chart'].__dict__.get('options3d'):
+ if len(htmlsrcdoc) < 99965000 :
+ return ''
+ else:
+ return ''
+ else:
+ return ''
+
+
def __str__(self):
"""return htmlcontent"""
#self.buildhtml()
diff --git a/highcharts/highcharts/options.py b/highcharts/highcharts/options.py
index 85e7689..d91b827 100644
--- a/highcharts/highcharts/options.py
+++ b/highcharts/highcharts/options.py
@@ -4,7 +4,7 @@
from .highchart_types import OptionTypeError, Series, SeriesOptions
from .common import Formatter, Events, Position, ContextButton, Options3d, ResetZoomButton, \
DrillUpButton, Labels, PlotBands, PlotLines, Title, Items, Navigation, Background, Breaks, \
- DateTimeLabelFormats, Zones, Levels, \
+ DataClasses, DateTimeLabelFormats, Zones, Levels, Marker, \
JSfunction, ColorObject, CSSObject, SVGObject, CommonObject, ArrayObject
import json, datetime
@@ -153,6 +153,52 @@ class ChartOptions(BaseOptions):
}
+class ColorAxisOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "dataClassColor": basestring,
+ "dataClasses": (DataClasses, dict),
+ "endOnTick": bool,
+ "events": (Events, dict),
+ "gridLineColor": (ColorObject, basestring, dict),
+ "gridLineDashStyle": basestring,
+ "gridLineWidth": [float, int],
+ "id": basestring,
+ "labels": (Labels, dict),
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": [float, int],
+ "marker": (Marker, dict),
+ "max": [float, int],
+ "maxColor": (ColorObject, basestring, dict),
+ "maxPadding": [float, int],
+ "min": [float, int],
+ "minColor": (ColorObject, basestring, dict),
+ "minPadding": [float, int],
+ "minorGridLineColor": (ColorObject, basestring, dict),
+ "minorGridLineDashStyle": basestring,
+ "minorGridLineWidth": int,
+ "minorTickColor": (ColorObject, basestring, dict),
+ "minorTickInterval": int,
+ "minorTickLength": int,
+ "minorTickPosition": basestring,
+ "minorTickWidth": int,
+ "reversed": bool,
+ "showFirstLabel": bool,
+ "showLastLabel": bool,
+ "startOfWeek": int,
+ "startOnTick": bool,
+ "stops": list,
+ "tickColor": (ColorObject, basestring, dict),
+ "tickInterval": int,
+ "tickLength": int,
+ "tickPixelInterval": int,
+ "tickPosition": basestring,
+ "tickPositioner": JSfunction,
+ "tickPositions": list,
+ "tickWidth": int,
+ "type": basestring,
+}
+
+
class ColorsOptions(BaseOptions):
""" Special Case, this is simply just an array of colours """
def __init__(self):
@@ -389,6 +435,7 @@ class TooltipOptions(BaseOptions):
"formatter": (Formatter, JSfunction),
"headerFormat": basestring,
"pointFormat": basestring,
+ "pointFormatter": (Formatter, JSfunction),
"positioner": (JSfunction, basestring),
"shadow": bool,
"shared": bool,
diff --git a/highcharts/highcharts/templates/content.html b/highcharts/highcharts/templates/content.html
index 64e3e86..b92181e 100644
--- a/highcharts/highcharts/templates/content.html
+++ b/highcharts/highcharts/templates/content.html
@@ -5,19 +5,14 @@
{% block body_head %}
- {% if chart.jsonp_data_flag %}
- $.getJSON({{chart.jsonp_data_url}}, function ({{chart.jsonp_data}})
- {
- {% endif %}
+ {% if chart.jscript_head_flag %}
+ {{chart.jscript_head}}
+ {% endif %}
{% endblock body_head %}
{% block body_content %}
- {% if chart.jscript_head_flag %}
- {{chart.jscript_head}}
- {% endif %}
-
Highcharts.setOptions({{chart.setoption}});
var option = {{chart.option}};
@@ -25,9 +20,6 @@
var geojson = {{chart.mapdata}}
{% endif %}
- var data = {{chart.data}};
- option.series = data;
-
{% if chart.drilldown_flag %}
var drilldowndata = {{chart.drilldown_data}};
option.drilldown.series = drilldowndata;
@@ -35,6 +27,26 @@
var chart = new Highcharts.Chart(option);
+ {# DEM 2017/07/27: Use a list of JSONP data sources
+ {# DEM 2017/07/27: This implementation is limited and could easily be improved! #}
+ {% if chart.jsonp_data_flag %}
+ {% for data_url in chart.jsonp_data_url_list %}
+
+ $.getJSON({{data_url}}, function ({{chart.jsonp_data}})
+ {
+ chart.addSeries({{chart.data_list[loop.index0]}});
+ });
+
+ {% endfor %}
+ {% else %}
+ var data = {{chart.data}};
+ var dataLen = data.length;
+ for (var ix = 0; ix < dataLen; ix++) {
+ chart.addSeries(data[ix]);
+ }
+ {% endif %}
+
+
{% if chart.jscript_end_flag %}
{{chart.jscript_end}}
{% endif %}
@@ -73,8 +85,4 @@
{% block body_end %}
- {% if chart.jsonp_data_flag %}
- });
- {% endif %}
-
-{% endblock body_end %}
\ No newline at end of file
+{% endblock body_end %}
diff --git a/highcharts/highmaps/highmaps.py b/highcharts/highmaps/highmaps.py
index 0fc67f3..0d73afc 100644
--- a/highcharts/highmaps/highmaps.py
+++ b/highcharts/highmaps/highmaps.py
@@ -6,12 +6,13 @@
from past.builtins import basestring
-from optparse import OptionParser
from urllib.request import urlopen
from jinja2 import Environment, PackageLoader
import json, uuid
-import datetime, random, os, inspect
+import re
+import datetime
+import html
from collections import Iterable
from .options import BaseOptions, ChartOptions, \
ColorsOptions, ColorAxisOptions, CreditsOptions, DrilldownOptions, ExportingOptions, \
@@ -64,12 +65,12 @@ def __init__(self, **kwargs):
# Set Javascript src
self.JSsource = [
- 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js',
- 'https://code.highcharts.com/maps/highmaps.js',
- 'https://code.highcharts.com/highcharts.js',
- 'https://code.highcharts.com/maps/modules/map.js',
- 'https://code.highcharts.com/maps/modules/data.js',
- 'https://code.highcharts.com/maps/modules/exporting.js'
+ 'https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js',
+ 'https://code.highcharts.com/maps/6/highmaps.js',
+ 'https://code.highcharts.com/6/highcharts.js',
+ 'https://code.highcharts.com/maps/6/modules/map.js',
+ 'https://code.highcharts.com/maps/6/modules/data.js',
+ 'https://code.highcharts.com/maps/6/modules/exporting.js'
]
# set CSS src
@@ -327,6 +328,8 @@ def set_options(self, option_type, option_dict, force_options=False):
elif option_type == 'colorAxis':
self.options.update({'colorAxis': self.options.get('colorAxis', ColorAxisOptions())})
self.options[option_type].update_dict(**option_dict)
+ elif option_type in ["global" , "lang"]:
+ self.setOptions[option_type].update_dict(**option_dict)
else:
self.options[option_type].update_dict(**option_dict)
@@ -369,7 +372,7 @@ def buildhtml(self):
self.buildcontent()
self.buildhtmlheader()
self.content = self._htmlcontent.decode('utf-8') # need to ensure unicode
- self._htmlcontent = self.template_page_highcharts.render(chart=self).encode('utf-8')
+ self._htmlcontent = self.template_page_highcharts.render(chart=self)
return self._htmlcontent
def buildhtmlheader(self):
@@ -418,6 +421,23 @@ def buildcontainer(self):
def htmlcontent(self):
return self.buildhtml()
+ @property
+ def iframe(self):
+ htmlsrcdoc = html.escape(self.htmlcontent)
+ htmlsrcdoc = re.sub('\\n', ' ', htmlsrcdoc)
+ htmlsrcdoc = re.sub(' +', ' ', htmlsrcdoc)
+ width = int(self.options['chart'].__dict__['width']) if self.options['chart'].__dict__.get('width') else 820
+ height = int(self.options['chart'].__dict__['height']) if self.options['chart'].__dict__.get('height') else 520
+
+ if self.options['chart'].__dict__.get('options3d'):
+ if len(htmlsrcdoc) < 99965000 :
+ return ''
+ else:
+ return ''
+ else:
+ return ''
+
def __str__(self):
"""return htmlcontent"""
#self.buildhtml()
diff --git a/highcharts/highstock/highstock.py b/highcharts/highstock/highstock.py
index 624c9fb..ef8610d 100644
--- a/highcharts/highstock/highstock.py
+++ b/highcharts/highstock/highstock.py
@@ -4,11 +4,12 @@
from future.standard_library import install_aliases
install_aliases()
-from optparse import OptionParser
from jinja2 import Environment, PackageLoader
import json, uuid
-import datetime, random, os, inspect
+import re
+import datetime
+import html
from collections import Iterable
from .options import BaseOptions, ChartOptions, \
ColorsOptions, CreditsOptions, ExportingOptions, \
@@ -60,10 +61,10 @@ def __init__(self, **kwargs):
# set Javascript src, Highcharts lib needs to make sure it's up to date
self.JSsource = [
- 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js',
- 'https://code.highcharts.com/stock/highstock.js',
- 'https://code.highcharts.com/stock/modules/exporting.js',
- 'https://code.highcharts.com/highcharts-more.js',
+ 'https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js',
+ 'https://code.highcharts.com/stock/6/highstock.js',
+ 'https://code.highcharts.com/stock/6/modules/exporting.js',
+ 'https://code.highcharts.com/6/highcharts-more.js',
]
# set CSS src
@@ -82,6 +83,7 @@ def __init__(self, **kwargs):
# Data from jsonp
self.jsonp_data_flag = False
+ self.jsonp_data_url_list = [] # DEM 2017/04/25: List of JSON data sources
# javascript
self.jscript_head_flag = False
@@ -205,13 +207,15 @@ def add_data_from_jsonp(self, data_src, data_name='json_data', series_type="line
"""
if not self.jsonp_data_flag:
self.jsonp_data_flag = True
- self.jsonp_data_url = json.dumps(data_src)
if data_name == 'data':
data_name = 'json_'+ data_name
self.jsonp_data = data_name
self.add_data_set(RawJavaScriptText(self.jsonp_data), series_type, name=name, **kwargs)
+ # DEM 2017/04/25: Append new JSON data source to a list instead of
+ # replacing whatever already exists
+ self.jsonp_data_url_list.append(json.dumps(data_src))
def add_navi_series(self, data, series_type="line", **kwargs):
@@ -269,6 +273,8 @@ def set_options(self, option_type, option_dict, force_options=False):
self.options[option_type].update(**each_dict)
elif option_type == 'colors':
self.options["colors"].set_colors(option_dict) # option_dict should be a list
+ elif option_type in ["global" , "lang"]: #Highcharts.setOptions:
+ self.setOptions[option_type].update_dict(**option_dict)
else:
self.options[option_type].update_dict(**option_dict)
@@ -291,6 +297,11 @@ def buildcontent(self):
self.option = json.dumps(self.options, cls = HighchartsEncoder)
self.setoption = json.dumps(self.setOptions, cls = HighchartsEncoder)
self.data = json.dumps(self.data_temp, cls = HighchartsEncoder)
+
+ # DEM 2017/04/25: Make 'data' available as an array
+ # ... this permits jinja2 array access to each data definition
+ # ... which is useful for looping over multiple data sources
+ self.data_list = [json.dumps(x, cls = HighchartsEncoder) for x in self.data_temp]
if self.navi_seri_flag:
self.navi_seri = json.dumps(self.navi_seri_temp, cls = HighchartsEncoder)
@@ -306,7 +317,7 @@ def buildhtml(self):
self.buildcontent()
self.buildhtmlheader()
self.content = self._htmlcontent.decode('utf-8') # need to ensure unicode
- self._htmlcontent = self.template_page_highcharts.render(chart=self).encode('utf-8')
+ self._htmlcontent = self.template_page_highcharts.render(chart=self)
return self._htmlcontent
@@ -352,6 +363,23 @@ def buildcontainer(self):
def htmlcontent(self):
return self.buildhtml()
+ @property
+ def iframe(self):
+ htmlsrcdoc = html.escape(self.htmlcontent)
+ htmlsrcdoc = re.sub('\\n', ' ', htmlsrcdoc)
+ htmlsrcdoc = re.sub(' +', ' ', htmlsrcdoc)
+ width = int(self.options['chart'].__dict__['width']) if self.options['chart'].__dict__.get('width') else 820
+ height = int(self.options['chart'].__dict__['height']) if self.options['chart'].__dict__.get('height') else 520
+
+ if self.options['chart'].__dict__.get('options3d'):
+ if len(htmlsrcdoc) < 99965000 :
+ return ''
+ else:
+ return ''
+ else:
+ return ''
+
def __str__(self):
"""return htmlcontent"""
#self.buildhtml()
diff --git a/highcharts/highstock/options.py b/highcharts/highstock/options.py
index 18fa235..4a21318 100644
--- a/highcharts/highstock/options.py
+++ b/highcharts/highstock/options.py
@@ -301,6 +301,7 @@ class PlotOptions(BaseOptions):
"arearange": (SeriesOptions, dict),
"areaspline": (SeriesOptions, dict),
"areasplinerange": (SeriesOptions, dict),
+ "candlestick": (SeriesOptions, dict),
"column": (SeriesOptions, dict),
"columnrange": (SeriesOptions, dict),
"flags": (SeriesOptions, dict),
@@ -541,6 +542,11 @@ class yAxisOptions(BaseOptions):
"tickmarkPlacement": basestring,
"title": (Title, dict),
"top": [int, float, basestring],
+ # DEM 2017/11/16: Note that the 'type' keyword for highstock is
+ # undocumented yet appears to be supported, likely because of underlying
+ # shared code. This permits logarithmic Y-Axis scale which is
+ # frequently useful in stock charts.
+ "type": basestring,
"units": list
}
diff --git a/highcharts/highstock/templates/content.html b/highcharts/highstock/templates/content.html
index 4eade17..54615ba 100644
--- a/highcharts/highstock/templates/content.html
+++ b/highcharts/highstock/templates/content.html
@@ -5,25 +5,17 @@
{% block body_head %}
- {% if chart.jsonp_data_flag %}
- $.getJSON({{chart.jsonp_data_url}}, function ({{chart.jsonp_data}})
- {
- {% endif %}
+ {% if chart.jscript_head_flag %}
+ {{chart.jscript_head}}
+ {% endif %}
{% endblock body_head %}
{% block body_content %}
- {% if chart.jscript_head_flag %}
- {{chart.jscript_head}}
- {% endif %}
-
Highcharts.setOptions({{chart.setoption}});
var option = {{chart.option}};
- var data = {{chart.data}};
- option.series = data;
-
{% if chart.navi_seri_flag %}
var navi_data = {{chart.navi_seri}}
option.navigator.series = navi_data;
@@ -31,16 +23,34 @@
var chart = new Highcharts.StockChart(option);
- {% if chart.jscript_end_flag %}
- {{chart.jscript_end}}
- {% endif %}
+
+ {# DEM 2017/04/25: Use a list of JSONP data sources
+ {# DEM 2017/07/27: This implementation is limited and could easily be improved! #}
+ {% if chart.jsonp_data_flag %}
+ {% for data_url in chart.jsonp_data_url_list %}
+
+ $.getJSON({{data_url}}, function ({{chart.jsonp_data}})
+ {
+ chart.addSeries({{chart.data_list[loop.index0]}});
+ });
+
+ {% endfor %}
+ {% else %}
+
+ var data = {{chart.data}};
+ var dataLen = data.length;
+ for (var ix = 0; ix < dataLen; ix++) {
+ chart.addSeries(data[ix]);
+ }
+
+ {% endif %}
{% endblock body_content %}
{% block body_end %}
- {% if chart.jsonp_data_flag %}
- });
- {% endif %}
+ {% if chart.jscript_end_flag %}
+ {{chart.jscript_end}}
+ {% endif %}
-{% endblock body_end %}
\ No newline at end of file
+{% endblock body_end %}
diff --git a/highcharts/highstock/templates/page.html b/highcharts/highstock/templates/page.html
index 3559aaa..dd722fe 100644
--- a/highcharts/highstock/templates/page.html
+++ b/highcharts/highstock/templates/page.html
@@ -8,5 +8,6 @@
{{ chart.content }}
+ {{ chart.other }}