Skip to content

Commit

Permalink
JSONP multisource support (#42)
Browse files Browse the repository at this point in the history
* Add multiple JSONP data sources, assuming all data comes from JSONP

* Add array version of data definition for improving the jinja2 template

* Fix bug in Highchart add jsonp url

* Apply multi-source JSONP code to highcharts

* Update inline comments for clarity and accuracy

* Update variable name to 'data_list' as per request for style consistency
  • Loading branch information
othalan authored and ksolan committed Dec 19, 2017
1 parent d59f9f8 commit 6456782
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 60 deletions.
31 changes: 16 additions & 15 deletions highcharts/highcharts/highchart_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -623,22 +623,23 @@ 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,
Expand Down
31 changes: 21 additions & 10 deletions highcharts/highcharts/highcharts.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,12 @@ def __init__(self, **kwargs):
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)
Expand Down Expand Up @@ -220,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)

Expand All @@ -233,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):
Expand Down Expand Up @@ -305,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')
Expand Down
40 changes: 24 additions & 16 deletions highcharts/highcharts/templates/content.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,48 @@

{% 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}};

{% if chart.mapdata_flag %}
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;
{% endif %}

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 %}
Expand Down Expand Up @@ -73,8 +85,4 @@

{% block body_end %}

{% if chart.jsonp_data_flag %}
});
{% endif %}

{% endblock body_end %}
{% endblock body_end %}
10 changes: 9 additions & 1 deletion highcharts/highstock/highstock.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,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
Expand Down Expand Up @@ -206,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):
Expand Down Expand Up @@ -294,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)
Expand Down
46 changes: 28 additions & 18 deletions highcharts/highstock/templates/content.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,52 @@

{% 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;
{% endif %}

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 %}
{% endblock body_end %}
1 change: 1 addition & 0 deletions highcharts/highstock/templates/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
</head>
<body style="margin:0;padding:0">
{{ chart.content }}
{{ chart.other }}
</body>
</html>

0 comments on commit 6456782

Please sign in to comment.