From 95a1bd38cac59f2e68890d69b095da9e5c33f55d Mon Sep 17 00:00:00 2001 From: fx_kirin Date: Mon, 9 Sep 2019 20:06:06 +0900 Subject: [PATCH] fixjsonp_data --- highcharts/highstock/highstock.py | 123 +++++++++----------- highcharts/highstock/templates/content.html | 6 +- 2 files changed, 57 insertions(+), 72 deletions(-) diff --git a/highcharts/highstock/highstock.py b/highcharts/highstock/highstock.py index 0b5c4c0..7f9513d 100644 --- a/highcharts/highstock/highstock.py +++ b/highcharts/highstock/highstock.py @@ -7,7 +7,8 @@ from jinja2 import Environment, PackageLoader -import json, uuid +import json +import uuid import re import datetime import html @@ -31,7 +32,7 @@ template_content = jinja2_env.get_template(CONTENT_FILENAME) template_page = jinja2_env.get_template(PAGE_FILENAME) - + class Highstock(object): """ @@ -59,20 +60,20 @@ 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.9.1/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/highstock.js', + 'https://code.highcharts.com/stock/modules/exporting.js', + 'https://code.highcharts.com/highcharts-more.js', + ] # set CSS src self.CSSsource = [ - 'https://www.highcharts.com/highslide/highslide.css', + 'https://www.highcharts.com/highslide/highslide.css', - ] + ] # set data self.data = [] self.data_temp = [] @@ -84,8 +85,8 @@ 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 - + self.jsonp_data_url_list = [] # DEM 2017/04/25: List of JSON data sources + # javascript self.jscript_head_flag = False self.jscript_head = kwargs.get('jscript_head', None) @@ -155,18 +156,16 @@ def __init__(self, **kwargs): for keyword in allowed_kwargs: if keyword in kwargs: - self.options['chart'].update_dict(**{keyword:kwargs[keyword]}) + self.options['chart'].update_dict(**{keyword: kwargs[keyword]}) # Some Extra Vals to store: self.data_set_count = 0 self.drilldown_data_set_count = 0 - def __load_defaults__(self): self.options["chart"].update_dict(renderTo='container') self.options["title"].update_dict(text='A New Highchart') self.options["credits"].update_dict(enabled=False) - def add_JSsource(self, new_src): """add additional js script source(s)""" if isinstance(new_src, list): @@ -177,7 +176,6 @@ def add_JSsource(self, new_src): else: raise OptionTypeError("Option: %s Not Allowed For Series Type: %s" % type(new_src)) - def add_CSSsource(self, new_src): """add additional css source(s)""" if isinstance(new_src, list): @@ -188,44 +186,37 @@ def add_CSSsource(self, new_src): else: raise OptionTypeError("Option: %s Not Allowed For Series Type: %s" % type(new_src)) - def add_data_set(self, data, series_type="line", name=None, **kwargs): """set data for series option in highstocks""" self.data_set_count += 1 if not name: name = "Series %d" % self.data_set_count - kwargs.update({'name':name}) + kwargs.update({'name': name}) series_data = Series(data, series_type=series_type, **kwargs) series_data.__options__().update(SeriesOptions(series_type=series_type, **kwargs).__options__()) self.data_temp.append(series_data) - - def add_data_from_jsonp(self, data_src, data_name='json_data', series_type="line", name=None, **kwargs): + def add_data_from_jsonp(self, data_src, series_type="line", name=None, **kwargs): """set map data directly from a https source the data_src is the https link for data and it must be in jsonp format """ 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(self.jsonp_data), series_type, name=name, **kwargs) + + self.add_data_set(None, 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): """set series for navigator option in highstocks""" self.navi_seri_flag = True series_data = Series(data, series_type=series_type, **kwargs) - series_data.__options__().update(SeriesOptions(series_type=series_type, **kwargs).__options__()) + series_data.__options__().update(SeriesOptions(series_type=series_type, **kwargs).__options__()) self.navi_seri_temp = series_data def add_navi_series_from_jsonp(self, data_src=None, data_name='json_data', series_type="line", **kwargs): @@ -233,15 +224,12 @@ def add_navi_series_from_jsonp(self, data_src=None, data_name='json_data', serie if not self.jsonp_data_flag: self.jsonp_data_flag = True - self.jsonp_data_url = json.dumps(data_src) - + self.jsonp_data_url = json.dumps(data_src) + if data_name == 'data': - data_name = 'json_'+ data_name - - self.jsonp_data = data_name - - self.add_navi_series(RawJavaScriptText(self.jsonp_data), series_type, **kwargs) + data_name = 'json_' + data_name + self.add_navi_series(RawJavaScriptText(self.jsonp_data), series_type, **kwargs) def add_JSscript(self, js_script, js_loc): """add (highcharts) javascript in the beginning or at the end of script @@ -250,19 +238,18 @@ def add_JSscript(self, js_script, js_loc): if js_loc == 'head': self.jscript_head_flag = True if self.jscript_head: - self.jscript_head = self.jscript_head + '\n' + js_script + self.jscript_head = self.jscript_head + '\n' + js_script else: self.jscript_head = js_script elif js_loc == 'end': self.jscript_end_flag = True if self.jscript_end: - self.jscript_end = self.jscript_end + '\n' + js_script + self.jscript_end = self.jscript_end + '\n' + js_script else: self.jscript_end = js_script else: - raise OptionTypeError("Not An Accepted script location: %s, either 'head' or 'end'" - % js_loc) - + raise OptionTypeError("Not An Accepted script location: %s, either 'head' or 'end'" + % js_loc) def set_options(self, option_type, option_dict, force_options=False): """set plot options """ @@ -274,13 +261,12 @@ def set_options(self, option_type, option_dict, force_options=False): for each_dict in option_dict: 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.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) - def set_dict_options(self, options): """for dictionary-like inputs (as object in Javascript) options must be in python dictionary format @@ -289,27 +275,25 @@ def set_dict_options(self, options): for key, option_data in options.items(): self.set_options(key, option_data) else: - raise OptionTypeError("Not An Accepted Input Format: %s. Must be Dictionary" %type(options)) - + raise OptionTypeError("Not An Accepted Input Format: %s. Must be Dictionary" % type(options)) def buildcontent(self): """build HTML content only, no header or body tags""" self.buildcontainer() - 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) + 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) + self.data_list = [json.dumps(x, cls=HighchartsEncoder) for x in self.data_temp] - self._htmlcontent = self.template_content_highcharts.render(chart=self).encode('utf-8') + if self.navi_seri_flag: + self.navi_seri = json.dumps(self.navi_seri_temp, cls=HighchartsEncoder) + self._htmlcontent = self.template_content_highcharts.render(chart=self).encode('utf-8') def buildhtml(self): """build the HTML page @@ -318,10 +302,9 @@ def buildhtml(self): """ self.buildcontent() self.buildhtmlheader() - self.content = self._htmlcontent.decode('utf-8') # need to ensure unicode + self.content = self._htmlcontent.decode('utf-8') # need to ensure unicode self._htmlcontent = self.template_page_highcharts.render(chart=self) return self._htmlcontent - def buildhtmlheader(self): """generate HTML header content""" @@ -340,7 +323,6 @@ def buildhtmlheader(self): for js in self.header_js: self.htmlheader += js - def buildcontainer(self): """generate HTML div""" if self.container: @@ -357,7 +339,7 @@ def buildcontainer(self): else: self.div_style += 'height:%s;' % self.options['chart'].height - self.div_name = self.options['chart'].__dict__['renderTo'] # recheck div name + self.div_name = self.options['chart'].__dict__['renderTo'] # recheck div name self.container = self.containerheader + \ '
%s
\n' % (self.div_name, self.div_style, self.loading) @@ -372,31 +354,32 @@ def iframe(self): 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 '' + if len(htmlsrcdoc) < 99965000: + return '' else: - return '' + return '' else: - return '' + return '' def __str__(self): """return htmlcontent""" #self.buildhtml() return self.htmlcontent - def save_file(self, filename = 'StockChart'): + def save_file(self, filename='StockChart'): """ save htmlcontent as .html file """ filename = filename + '.html' - + with open(filename, 'w') as f: #self.buildhtml() f.write(self.htmlcontent) - + f.closed + class HighchartsEncoder(json.JSONEncoder): def __init__(self, *args, **kwargs): json.JSONEncoder.__init__(self, *args, **kwargs) @@ -410,12 +393,12 @@ def default(self, obj): elif isinstance(obj, datetime.datetime): utc = obj.utctimetuple() obj = (u"Date.UTC({year},{month},{day},{hours},{minutes},{seconds},{millisec})" - .format(year=utc[0], month=utc[1]-1, day=utc[2], hours=utc[3], - minutes=utc[4], seconds=utc[5], millisec=obj.microsecond/1000)) + .format(year=utc[0], month=utc[1] - 1, day=utc[2], hours=utc[3], + minutes=utc[4], seconds=utc[5], millisec=obj.microsecond / 1000)) return RawJavaScriptText(obj) elif isinstance(obj, BaseOptions) or isinstance(obj, MultiAxis): return obj.__jsonable__() - elif isinstance(obj, CSSObject) or isinstance(obj, Formatter) or isinstance(obj, JSfunction): + elif isinstance(obj, CSSObject) or isinstance(obj, Formatter) or isinstance(obj, JSfunction): return obj.__jsonable__() elif isinstance(obj, SeriesOptions) or isinstance(obj, Series): return obj.__jsonable__() @@ -433,5 +416,5 @@ def encode(self, obj): class OptionTypeError(Exception): - def __init__(self,*args): + def __init__(self, *args): self.args = args diff --git a/highcharts/highstock/templates/content.html b/highcharts/highstock/templates/content.html index 54615ba..f49c47a 100644 --- a/highcharts/highstock/templates/content.html +++ b/highcharts/highstock/templates/content.html @@ -29,9 +29,11 @@ {% if chart.jsonp_data_flag %} {% for data_url in chart.jsonp_data_url_list %} - $.getJSON({{data_url}}, function ({{chart.jsonp_data}}) + $.getJSON({{data_url}}, function (json) { - chart.addSeries({{chart.data_list[loop.index0]}}); + var data = {{chart.data}}[{{loop.index0}}]; + data.data = json; + chart.addSeries(data); }); {% endfor %}