From 8f9edb9a102af7cb401c59c21deff928e891c9de Mon Sep 17 00:00:00 2001 From: "Kunal Chavda (OpenERP)" Date: Thu, 7 Apr 2011 19:00:26 +0530 Subject: [PATCH 01/40] [ADD]view_graph at initial level. bzr revid: kch@tinyerp.com-20110407133026-wtotf1dlj7m2wadf --- addons/base/controllers/main.py | 10 +- addons/base/static/src/base.html | 3 + addons/base/static/src/js/base.js | 3 +- addons/base/static/src/xml/base.xml | 3 + addons/base_graph/__init__.py | 2 + addons/base_graph/__openerp__.py | 7 + addons/base_graph/controllers/__init__.py | 1 + addons/base_graph/controllers/main.py | 69 + .../static/dhtmlxGraph/License_GPL.html | 73 + .../dhtmlxGraph/codebase/dhtmlxchart.css | 6 + .../dhtmlxGraph/codebase/dhtmlxchart.js | 131 + .../codebase/dhtmlxchart_debug.css | 6 + .../dhtmlxGraph/codebase/dhtmlxchart_debug.js | 4737 +++++++++++++++++ .../codebase/thirdparty/excanvas/AUTHORS | 10 + .../codebase/thirdparty/excanvas/COPYING | 202 + .../codebase/thirdparty/excanvas/README | 22 + .../codebase/thirdparty/excanvas/excanvas.js | 927 ++++ .../static/dhtmlxGraph/dhtmlxchart_full.zip | Bin 0 -> 22694 bytes .../base_graph/static/dhtmlxGraph/readme.txt | 7 + .../01_initialization/01_load_xml.html | 70 + .../01_initialization/02_load_json.html | 63 + .../01_initialization/03_load_csv.html | 65 + .../01_initialization/04_load_jsarray.html | 68 + .../samples/01_initialization/05_series.html | 119 + .../samples/02_color/01_default.html | 66 + .../samples/02_color/02_custom.html | 67 + .../samples/02_color/03_custom_logic.html | 77 + .../samples/02_color/04_gradient.html | 64 + .../samples/03_group/01_basic.html | 96 + .../samples/03_group/02_scales.html | 126 + .../samples/04_pie_chart/01_init.html | 67 + .../samples/04_pie_chart/02_text.html | 52 + .../samples/04_pie_chart/03_3d_chart.html | 48 + .../samples/04_pie_chart/04_legend.html | 81 + .../samples/05_line_chart/01_init.html | 55 + .../samples/05_line_chart/02_style.html | 153 + .../samples/05_line_chart/03_scale.html | 101 + .../samples/05_line_chart/04_spline.html | 57 + .../samples/05_line_chart/05_series.html | 94 + .../samples/06_bar_chart/01_init.html | 74 + .../samples/06_bar_chart/02_text.html | 80 + .../samples/06_bar_chart/03_scales.html | 99 + .../samples/06_bar_chart/04_styles.html | 207 + .../06_bar_chart/05_stacked_chart.html | 87 + .../samples/06_bar_chart/06_series.html | 81 + .../06_bar_chart/07_horizonal_bars.html | 120 + .../08_horizonal_stacked_bars.html | 75 + .../samples/07_area_chart/01_init.html | 55 + .../samples/07_area_chart/02_scale.html | 101 + .../samples/07_area_chart/03_series.html | 90 + .../07_area_chart/03_stacked_area.html | 88 + .../samples/08_dynamic/01_add.html | 83 + .../samples/08_dynamic/02_events.html | 96 + .../samples/08_dynamic/03_sorting.html | 73 + .../samples/08_dynamic/04_filtering.html | 81 + .../samples/09_integration/01_dhtmlxgrid.html | 70 + .../09_integration/02_dhtmlxgrid_group.html | 79 + .../samples/09_integration/03_windows.html | 77 + .../dhtmlxGraph/samples/common/config.php | 13 + .../dhtmlxGraph/samples/common/data.php | 16 + .../dhtmlxGraph/samples/common/sales.xml | 46 + .../dhtmlxGraph/samples/common/stat.xml | 1 + .../static/dhtmlxGraph/samples/readme.txt | 7 + .../static/dhtmlxGraph/sources/dhtmlxchart.js | 3498 ++++++++++++ addons/base_graph/static/openerp/js/graph.js | 71 + 65 files changed, 13170 insertions(+), 6 deletions(-) create mode 100644 addons/base_graph/__init__.py create mode 100644 addons/base_graph/__openerp__.py create mode 100644 addons/base_graph/controllers/__init__.py create mode 100644 addons/base_graph/controllers/main.py create mode 100644 addons/base_graph/static/dhtmlxGraph/License_GPL.html create mode 100644 addons/base_graph/static/dhtmlxGraph/codebase/dhtmlxchart.css create mode 100644 addons/base_graph/static/dhtmlxGraph/codebase/dhtmlxchart.js create mode 100644 addons/base_graph/static/dhtmlxGraph/codebase/dhtmlxchart_debug.css create mode 100644 addons/base_graph/static/dhtmlxGraph/codebase/dhtmlxchart_debug.js create mode 100644 addons/base_graph/static/dhtmlxGraph/codebase/thirdparty/excanvas/AUTHORS create mode 100644 addons/base_graph/static/dhtmlxGraph/codebase/thirdparty/excanvas/COPYING create mode 100644 addons/base_graph/static/dhtmlxGraph/codebase/thirdparty/excanvas/README create mode 100644 addons/base_graph/static/dhtmlxGraph/codebase/thirdparty/excanvas/excanvas.js create mode 100644 addons/base_graph/static/dhtmlxGraph/dhtmlxchart_full.zip create mode 100644 addons/base_graph/static/dhtmlxGraph/readme.txt create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/01_initialization/01_load_xml.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/01_initialization/02_load_json.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/01_initialization/03_load_csv.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/01_initialization/04_load_jsarray.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/01_initialization/05_series.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/02_color/01_default.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/02_color/02_custom.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/02_color/03_custom_logic.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/02_color/04_gradient.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/03_group/01_basic.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/03_group/02_scales.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/04_pie_chart/01_init.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/04_pie_chart/02_text.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/04_pie_chart/03_3d_chart.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/04_pie_chart/04_legend.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/01_init.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/02_style.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/03_scale.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/04_spline.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/05_series.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/01_init.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/02_text.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/03_scales.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/04_styles.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/05_stacked_chart.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/06_series.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/07_horizonal_bars.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/08_horizonal_stacked_bars.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/07_area_chart/01_init.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/07_area_chart/02_scale.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/07_area_chart/03_series.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/07_area_chart/03_stacked_area.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/08_dynamic/01_add.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/08_dynamic/02_events.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/08_dynamic/03_sorting.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/08_dynamic/04_filtering.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/09_integration/01_dhtmlxgrid.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/09_integration/02_dhtmlxgrid_group.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/09_integration/03_windows.html create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/common/config.php create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/common/data.php create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/common/sales.xml create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/common/stat.xml create mode 100644 addons/base_graph/static/dhtmlxGraph/samples/readme.txt create mode 100644 addons/base_graph/static/dhtmlxGraph/sources/dhtmlxchart.js create mode 100644 addons/base_graph/static/openerp/js/graph.js diff --git a/addons/base/controllers/main.py b/addons/base/controllers/main.py index 92987ffa639..efd4a7bcef9 100644 --- a/addons/base/controllers/main.py +++ b/addons/base/controllers/main.py @@ -93,7 +93,7 @@ class Session(openerpweb.Controller): @openerpweb.jsonrequest def modules(self, req): - return {"modules": ["base", "base_hello", "base_calendar", "base_gantt"]} + return {"modules": ["base", "base_hello", "base_calendar", "base_gantt", "base_graph"]} @openerpweb.jsonrequest def csslist(self, req, mods='base,base_hello'): @@ -168,7 +168,7 @@ class Session(openerpweb.Controller): 'domain': domain, 'group_by': group_by_sequence } - + def load_actions_from_ir_values(req, key, key2, models, meta, context): Values = req.session.model('ir.values') actions = Values.get(key, key2, models, meta, context) @@ -239,7 +239,7 @@ class Menu(openerpweb.Controller): menu_items = Menus.read(menu_ids, ['name', 'sequence', 'parent_id']) menu_root = {'id': False, 'name': 'root', 'parent_id': [-1, '']} menu_items.append(menu_root) - + # make a tree using parent_id menu_items_map = dict((menu_item["id"], menu_item) for menu_item in menu_items) for menu_item in menu_items: @@ -479,10 +479,10 @@ class SearchView(View): def load(self, req, model, view_id): fields_view = self.fields_view_get(req.session, model, view_id, 'search') return {'fields_view': fields_view} - + class SideBar(View): _cp_path = "/base/sidebar" - + @openerpweb.jsonrequest def get_actions(self, request, model, object_id=0): result = load_actions_from_ir_values(request, "action", "client_action_multi", diff --git a/addons/base/static/src/base.html b/addons/base/static/src/base.html index 3bfadba0782..a6cff3d9de7 100644 --- a/addons/base/static/src/base.html +++ b/addons/base/static/src/base.html @@ -26,6 +26,8 @@ + + @@ -33,6 +35,7 @@ + + + + + + + + +

Chart data can be loaded from different sources: xml,json,JS array,csv
This samples demonstrates loading from xml file.

+
+
+ + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/01_initialization/02_load_json.html b/addons/base_graph/static/dhtmlxGraph/samples/01_initialization/02_load_json.html new file mode 100644 index 00000000000..e2ce20ae764 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/01_initialization/02_load_json.html @@ -0,0 +1,63 @@ + + + + + Data Loading: JSON + + + + + + + +
+
+ + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/01_initialization/03_load_csv.html b/addons/base_graph/static/dhtmlxGraph/samples/01_initialization/03_load_csv.html new file mode 100644 index 00000000000..64c39cfaef1 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/01_initialization/03_load_csv.html @@ -0,0 +1,65 @@ + + + + + Data Loading: CSV + + + + + + + +

When data are loaded from CSV string, you should use "data" and field index to define field in the template, for example, "#data0#","#data1#",etc.
Charts in this sample represents values in the first column. Therefore, we have set value:"#data0#" in a chart contructor.

+
+
+ + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/01_initialization/04_load_jsarray.html b/addons/base_graph/static/dhtmlxGraph/samples/01_initialization/04_load_jsarray.html new file mode 100644 index 00000000000..023cb0a503a --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/01_initialization/04_load_jsarray.html @@ -0,0 +1,68 @@ + + + + + Data Loading: JS array + + + + + + + + +

When data are loaded from JS array, you should use "data" and field index to define field in the template, for example, "#data0#","#data1#",etc.
Charts in this sample represents values in the first column. Therefore, we have set value:"#data0#" in a chart contructor.

+
+
+ + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/01_initialization/05_series.html b/addons/base_graph/static/dhtmlxGraph/samples/01_initialization/05_series.html new file mode 100644 index 00000000000..0600c05741d --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/01_initialization/05_series.html @@ -0,0 +1,119 @@ + + + + + PieChart: Initiazation + + + + +

BarChart: Scales

+ + + + + + + + + + +
Automatic vertical scaleCustom vertical scale
+ + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/02_color/01_default.html b/addons/base_graph/static/dhtmlxGraph/samples/02_color/01_default.html new file mode 100644 index 00000000000..39b2f5e3865 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/02_color/01_default.html @@ -0,0 +1,66 @@ + + + + + Colors: default + + + + + + + +

Chart colors are defined by color property. If it is not set, chart is colored using "rainbow" algorithm.

+
+
+ + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/02_color/02_custom.html b/addons/base_graph/static/dhtmlxGraph/samples/02_color/02_custom.html new file mode 100644 index 00000000000..8157a8f82b2 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/02_color/02_custom.html @@ -0,0 +1,67 @@ + + + + + Colors: custom colors + + + + + + + +

Colors can be defined with template. In this sample colors and defined in data by "color" field.

+
+
+ + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/02_color/03_custom_logic.html b/addons/base_graph/static/dhtmlxGraph/samples/02_color/03_custom_logic.html new file mode 100644 index 00000000000..e88c37b3283 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/02_color/03_custom_logic.html @@ -0,0 +1,77 @@ + + + + + Colors: custom logic + + + + + + + +

Colors can be defined using function. In this sample color of bars depends on sales value, and colors of pie sectors are alternative.

+
+
+ + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/02_color/04_gradient.html b/addons/base_graph/static/dhtmlxGraph/samples/02_color/04_gradient.html new file mode 100644 index 00000000000..973d9cdc008 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/02_color/04_gradient.html @@ -0,0 +1,64 @@ + + + + + Colors: color gradient + + + + + + + + + +

The color of Bar Chart can be defined by gradient property.
+ In this case you should set a function that takes a gradient object as an argument. And using addColorStop you may define colors for chart.

+
+ + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/03_group/01_basic.html b/addons/base_graph/static/dhtmlxGraph/samples/03_group/01_basic.html new file mode 100644 index 00000000000..401dbdae24f --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/03_group/01_basic.html @@ -0,0 +1,96 @@ + + + + + Grouping and Sorting + + + + + + + + +

It's possible to group chart data by a certain property. You may use group method or group property in a chart constructor.

+
+ + +
+ + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/03_group/02_scales.html b/addons/base_graph/static/dhtmlxGraph/samples/03_group/02_scales.html new file mode 100644 index 00000000000..75746062b29 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/03_group/02_scales.html @@ -0,0 +1,126 @@ + + + + + Scales and grouping + + + + + + + + +

To update configuration properties after grouping you need to cal define method with new settings.

+
+
+ + +

+ + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/04_pie_chart/01_init.html b/addons/base_graph/static/dhtmlxGraph/samples/04_pie_chart/01_init.html new file mode 100644 index 00000000000..63c82ecf42c --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/04_pie_chart/01_init.html @@ -0,0 +1,67 @@ + + + + + Initialization + + + + + + + + + + + + + + +
Pie chart with Automatic radius and center positionPie chart with Custom radius and center position
+ + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/04_pie_chart/02_text.html b/addons/base_graph/static/dhtmlxGraph/samples/04_pie_chart/02_text.html new file mode 100644 index 00000000000..7ba118f19e2 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/04_pie_chart/02_text.html @@ -0,0 +1,52 @@ + + + + + Labels + + + + + +

There are two properties to define sectors labels: +

  • label - defines text outside sectors
  • +
  • pieInnerText - set text inside sectors
  • +

    + +
    + + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/04_pie_chart/03_3d_chart.html b/addons/base_graph/static/dhtmlxGraph/samples/04_pie_chart/03_3d_chart.html new file mode 100644 index 00000000000..957f7ed7954 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/04_pie_chart/03_3d_chart.html @@ -0,0 +1,48 @@ + + + + + 3D view + + + + + +
    + + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/04_pie_chart/04_legend.html b/addons/base_graph/static/dhtmlxGraph/samples/04_pie_chart/04_legend.html new file mode 100644 index 00000000000..2d5c45c0151 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/04_pie_chart/04_legend.html @@ -0,0 +1,81 @@ + + + + + Details Block + + + + + +

    Pie Chart provides property "details" that displayes informationa about all sectors in a separate block.

    + + + + + + + + + + +
    PieChart with default details blockPieChart with custom details block
    + + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/01_init.html b/addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/01_init.html new file mode 100644 index 00000000000..626a1e216fe --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/01_init.html @@ -0,0 +1,55 @@ + + + + + Initialization + + + + + +
    + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/02_style.html b/addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/02_style.html new file mode 100644 index 00000000000..39dfe7eb41f --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/02_style.html @@ -0,0 +1,153 @@ + + + + + Style definition + + + + + + + + + + + + + + +
    + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/03_scale.html b/addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/03_scale.html new file mode 100644 index 00000000000..161cbf7ee53 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/03_scale.html @@ -0,0 +1,101 @@ + + + + + Scales + + + + + + + + + + + + + + +
    Automatic vertical scaleCustom vertical scale
    + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/04_spline.html b/addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/04_spline.html new file mode 100644 index 00000000000..4f266ee8983 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/04_spline.html @@ -0,0 +1,57 @@ + + + + + Initialization + + + + + +
    + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/05_series.html b/addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/05_series.html new file mode 100644 index 00000000000..532cd385519 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/05_line_chart/05_series.html @@ -0,0 +1,94 @@ + + + + + Scales + + + + + + + + + +
    + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/01_init.html b/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/01_init.html new file mode 100644 index 00000000000..e31ae20dd39 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/01_init.html @@ -0,0 +1,74 @@ + + + + + PieChart: Initiazation + + + + + +

    BarChart: Initiazation

    + + + + + + + + + + +
    + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/02_text.html b/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/02_text.html new file mode 100644 index 00000000000..ee378b194f1 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/02_text.html @@ -0,0 +1,80 @@ + + + + + PieChart: Initiazation + + + + +

    BarChart: Initiazation

    + + + + + + + + + + +
    + + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/03_scales.html b/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/03_scales.html new file mode 100644 index 00000000000..edc1f6ca45d --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/03_scales.html @@ -0,0 +1,99 @@ + + + + + PieChart: Initiazation + + + + +

    BarChart: Scales

    + + + + + + + + + + +
    Custom vertical scale and originAutomatic vertical scale
    + + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/04_styles.html b/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/04_styles.html new file mode 100644 index 00000000000..0877a95de16 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/04_styles.html @@ -0,0 +1,207 @@ + + + + + Chart + + + + +

    Chart

    + + + + + + + + + + + + + + + +
    + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/05_stacked_chart.html b/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/05_stacked_chart.html new file mode 100644 index 00000000000..d165d0bd488 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/05_stacked_chart.html @@ -0,0 +1,87 @@ + + + + + StackedBar Chart + + + + +

    StackedBar Chart

    +
    + + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/06_series.html b/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/06_series.html new file mode 100644 index 00000000000..3c5fb695692 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/06_series.html @@ -0,0 +1,81 @@ + + + + + Series + + + + +

    Series

    + +
    + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/07_horizonal_bars.html b/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/07_horizonal_bars.html new file mode 100644 index 00000000000..6c8046c5855 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/07_horizonal_bars.html @@ -0,0 +1,120 @@ + + + + + Horizontal bar Chart + + + + +

    Horizontal bar Chart

    + + + + + + + +
    + + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/08_horizonal_stacked_bars.html b/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/08_horizonal_stacked_bars.html new file mode 100644 index 00000000000..fe4d8509376 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/06_bar_chart/08_horizonal_stacked_bars.html @@ -0,0 +1,75 @@ + + + + + Horizontal Stacked Bars + + + + + +
    + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/07_area_chart/01_init.html b/addons/base_graph/static/dhtmlxGraph/samples/07_area_chart/01_init.html new file mode 100644 index 00000000000..5195e7476e1 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/07_area_chart/01_init.html @@ -0,0 +1,55 @@ + + + + + Initialization + + + + + +
    + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/07_area_chart/02_scale.html b/addons/base_graph/static/dhtmlxGraph/samples/07_area_chart/02_scale.html new file mode 100644 index 00000000000..e3d65bd6d55 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/07_area_chart/02_scale.html @@ -0,0 +1,101 @@ + + + + + Scales + + + + + + + + + + + + + + + +
    Custom vertical scaleAutomatic vertical scale
    + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/07_area_chart/03_series.html b/addons/base_graph/static/dhtmlxGraph/samples/07_area_chart/03_series.html new file mode 100644 index 00000000000..c071386c348 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/07_area_chart/03_series.html @@ -0,0 +1,90 @@ + + + + + Scales + + + + + + +
    + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/07_area_chart/03_stacked_area.html b/addons/base_graph/static/dhtmlxGraph/samples/07_area_chart/03_stacked_area.html new file mode 100644 index 00000000000..55fccb93e84 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/07_area_chart/03_stacked_area.html @@ -0,0 +1,88 @@ + + + + + Scales + + + + + + +
    + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/08_dynamic/01_add.html b/addons/base_graph/static/dhtmlxGraph/samples/08_dynamic/01_add.html new file mode 100644 index 00000000000..7a3b45f8cee --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/08_dynamic/01_add.html @@ -0,0 +1,83 @@ + + + + + Adding + + + + + + + + + +
    + + + + + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/08_dynamic/02_events.html b/addons/base_graph/static/dhtmlxGraph/samples/08_dynamic/02_events.html new file mode 100644 index 00000000000..495d42bf795 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/08_dynamic/02_events.html @@ -0,0 +1,96 @@ + + + + + Events + + + + + + + + + +
    +
    + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/08_dynamic/03_sorting.html b/addons/base_graph/static/dhtmlxGraph/samples/08_dynamic/03_sorting.html new file mode 100644 index 00000000000..cb8b254fe10 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/08_dynamic/03_sorting.html @@ -0,0 +1,73 @@ + + + + + Sorting + + + + + + + + + +
    + + + + + + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/08_dynamic/04_filtering.html b/addons/base_graph/static/dhtmlxGraph/samples/08_dynamic/04_filtering.html new file mode 100644 index 00000000000..230aa820800 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/08_dynamic/04_filtering.html @@ -0,0 +1,81 @@ + + + + + Filtering + + + + + + + + + +
    + + + + + + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/09_integration/01_dhtmlxgrid.html b/addons/base_graph/static/dhtmlxGraph/samples/09_integration/01_dhtmlxgrid.html new file mode 100644 index 00000000000..698da15d9fd --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/09_integration/01_dhtmlxgrid.html @@ -0,0 +1,70 @@ + + + + + + Integration with grid + + + + + + + + + + + + + +
    +
    +
    + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/09_integration/02_dhtmlxgrid_group.html b/addons/base_graph/static/dhtmlxGraph/samples/09_integration/02_dhtmlxgrid_group.html new file mode 100644 index 00000000000..d911e209922 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/09_integration/02_dhtmlxgrid_group.html @@ -0,0 +1,79 @@ + + + + + + Integration with Grid and Grouping + + + + + + + + + + + + + +
    +
    +
    + + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/09_integration/03_windows.html b/addons/base_graph/static/dhtmlxGraph/samples/09_integration/03_windows.html new file mode 100644 index 00000000000..822e621d9ca --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/09_integration/03_windows.html @@ -0,0 +1,77 @@ + + + + + + Integration with dhtmlxWindows + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/addons/base_graph/static/dhtmlxGraph/samples/common/config.php b/addons/base_graph/static/dhtmlxGraph/samples/common/config.php new file mode 100644 index 00000000000..3695ac3905a --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/common/config.php @@ -0,0 +1,13 @@ + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/common/data.php b/addons/base_graph/static/dhtmlxGraph/samples/common/data.php new file mode 100644 index 00000000000..ac8f5116a9d --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/common/data.php @@ -0,0 +1,16 @@ +"; + +for ($i=1; $i <= 100; $i++) { + $sales = rand(100,1000); + $year = rand(1996,2009); + $company = "Company ".rand(1,3); + $str.=""; +} + +$str .= ""; + +file_put_contents("stat.xml",$str); + +?> \ No newline at end of file diff --git a/addons/base_graph/static/dhtmlxGraph/samples/common/sales.xml b/addons/base_graph/static/dhtmlxGraph/samples/common/sales.xml new file mode 100644 index 00000000000..03c153cb1e5 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/common/sales.xml @@ -0,0 +1,46 @@ + + + 2.9 + 2000 + + + 3.5 + 2001 + + + 3.1 + 2002 + + + 4.2 + 2003 + + + 4.5 + 2004 + + + 7.4 + 2005 + + + 9.6 + 2006 + + + 9 + 2007 + + + 7.3 + 2008 + + + 5.8 + 2009 + + + 7.7 + 2010 + + diff --git a/addons/base_graph/static/dhtmlxGraph/samples/common/stat.xml b/addons/base_graph/static/dhtmlxGraph/samples/common/stat.xml new file mode 100644 index 00000000000..824ff6f6829 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/common/stat.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/addons/base_graph/static/dhtmlxGraph/samples/readme.txt b/addons/base_graph/static/dhtmlxGraph/samples/readme.txt new file mode 100644 index 00000000000..c1f4b60567c --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/samples/readme.txt @@ -0,0 +1,7 @@ +Next samples + 08_integration\01_dhtmlxgrid.html + 08_integration\02_dhtmlxgrid_group.html + 08_integration\03_layout.html +requires external components ( dhtmlxgrid and dhtmlxwindow ) + +Its recommended to run samples through any kind of webserver. diff --git a/addons/base_graph/static/dhtmlxGraph/sources/dhtmlxchart.js b/addons/base_graph/static/dhtmlxGraph/sources/dhtmlxchart.js new file mode 100644 index 00000000000..588c7fcee13 --- /dev/null +++ b/addons/base_graph/static/dhtmlxGraph/sources/dhtmlxchart.js @@ -0,0 +1,3498 @@ +/* +2010 July 02 +*/ + + + +/* DHX DEPEND FROM FILE 'assert.js'*/ + + +if (!window.dhtmlx) + dhtmlx={}; + +//check some rule, show message as error if rule is not correct +dhtmlx.assert = function(test, message){ + if (!test) dhtmlx.error(message); +}; +dhtmlx.assert_enabled=function(){ return false; }; + +//register names of event, which can be triggered by the object +dhtmlx.assert_event = function(obj, evs){ + if (!obj._event_check){ + obj._event_check = {}; + obj._event_check_size = {}; + } + + for (var a in evs){ + obj._event_check[a.toLowerCase()]=evs[a]; + var count=-1; for (var t in evs[a]) count++; + obj._event_check_size[a.toLowerCase()]=count; + } +}; +dhtmlx.assert_method_info=function(obj, name, descr, rules){ + var args = []; + for (var i=0; i < rules.length; i++) { + args.push(rules[i][0]+" : "+rules[i][1]+"\n "+rules[i][2].describe()+(rules[i][3]?"; optional":"")); + } + return obj.name+"."+name+"\n"+descr+"\n Arguments:\n - "+args.join("\n - "); +}; +dhtmlx.assert_method = function(obj, config){ + for (var key in config) + dhtmlx.assert_method_process(obj, key, config[key].descr, config[key].args, (config[key].min||99), config[key].skip); +}; +dhtmlx.assert_method_process = function (obj, name, descr, rules, min, skip){ + var old = obj[name]; + if (!skip) + obj[name] = function(){ + if (arguments.length != rules.length && arguments.length < min) + dhtmlx.log("warn","Incorrect count of parameters\n"+obj[name].describe()+"\n\nExpecting "+rules.length+" but have only "+arguments.length); + else + for (var i=0; i= 0) return true; + return false; + }; + dhtmlx.assert_rule_dimension.describe=function(){ + return "{Integer} value must be a positive number"; + }; + + dhtmlx.assert_rule_number=function(check){ + if (typeof check == "number") return true; + return false; + }; + dhtmlx.assert_rule_number.describe=function(){ + return "{Integer} value must be a number"; + }; + + dhtmlx.assert_rule_function=function(check){ + if (typeof check == "function") return true; + return false; + }; + dhtmlx.assert_rule_function.describe=function(){ + return "{Function} value must be a custom function"; + }; + + dhtmlx.assert_rule_any=function(check){ + return true; + }; + dhtmlx.assert_rule_any.describe=function(){ + return "Any value"; + }; + + dhtmlx.assert_rule_mix=function(a,b){ + var t = function(check){ + if (a(check)||b(check)) return true; + return false; + }; + t.describe = function(){ + return a.describe(); + }; + return t; + }; + +} + + +/* DHX DEPEND FROM FILE 'dhtmlx.js'*/ + + +/*DHX:Depend assert.js*/ + +/* + Common helpers +*/ +dhtmlx.version="3.0"; +dhtmlx.codebase="./"; + +//coding helpers + +//copies methods and properties from source to the target +dhtmlx.extend = function(target, source){ + for (var method in source) + target[method] = source[method]; + + //applying asserts + if (dhtmlx.assert_enabled() && source._assert){ + target._assert(); + target._assert=null; + } + + //if source object has init code - call init against target + if (source._init) + target._init(); + + return target; +}; +//creates function with specified "this" pointer +dhtmlx.bind=function(functor, object){ + return function(){ return functor.apply(object,arguments); }; +}; + +//loads module from external js file +dhtmlx.require=function(module){ + if (!dhtmlx._modules[module]){ + dhtmlx.assert(dhtmlx.ajax,"load module is required"); + + //load and exec the required module + dhtmlx.exec( dhtmlx.ajax().sync().get(dhtmlx.codebase+module).responseText ); + dhtmlx._modules[module]=true; + } +}; +dhtmlx._modules = {}; //hash of already loaded modules + +//evaluate javascript code in the global scoope +dhtmlx.exec=function(code){ + if (window.execScript) //special handling for IE + window.execScript(code); + else window.eval(code); +}; + +/* + creates method in the target object which will transfer call to the source object + if event parameter was provided , each call of method will generate onBefore and onAfter events +*/ +dhtmlx.methodPush=function(object,method,event){ + return function(){ + var res = false; + //if (!event || this.callEvent("onBefore"+event,arguments)){ //not used anymore, probably can be removed + res=object[method].apply(object,arguments); + // if (event) this.callEvent("onAfter"+event,arguments); + //} + return res; //result of wrapped method + }; +}; +//check === undefined +dhtmlx.isNotDefined=function(a){ + return typeof a == "undefined"; +}; +//delay call to after-render time +dhtmlx.delay=function(method, obj, params){ + setTimeout(function(){ + var ret = method.apply(obj,params); + method = obj = params = null; + return ret; + },1); +}; + +//common helpers + +//generates unique ID (unique per window, nog GUID) +dhtmlx.uid = function(){ + if (!this._seed) this._seed=(new Date).valueOf(); //init seed with timestemp + this._seed++; + return this._seed; +}; +//resolve ID as html object +dhtmlx.toNode = function(node){ + if (typeof node == "string") return document.getElementById(node); + return node; +}; +//adds extra methods for the array +dhtmlx.toArray = function(array){ + return dhtmlx.extend((array||[]),dhtmlx.PowerArray); +}; +//resolve function name +dhtmlx.toFunctor=function(str){ + return (typeof(str)=="string") ? eval(str) : str; +}; + +//dom helpers + +//hash of attached events +dhtmlx._events = {}; +//attach event to the DOM element +dhtmlx.event=function(node,event,handler,master){ + node = dhtmlx.toNode(node); + + var id = dhtmlx.uid(); + dhtmlx._events[id]=[node,event,handler]; //store event info, for detaching + + if (master) + handler=dhtmlx.bind(handler,master); + + //use IE's of FF's way of event's attaching + if (node.addEventListener) + node.addEventListener(event, handler, false); + else if (node.attachEvent) + node.attachEvent("on"+event, handler); + + return id; //return id of newly created event, can be used in eventRemove +}; + +//remove previously attached event +dhtmlx.eventRemove=function(id){ + + if (!id) return; + dhtmlx.assert(this._events[id],"Removing non-existing event"); + + var ev = dhtmlx._events[id]; + //browser specific event removing + if (ev[0].removeEventListener) + ev[0].removeEventListener(ev[1],ev[2],false); + else if (ev[0].detachEvent) + ev[0].detachEvent("on"+ev[1],ev[2]); + + delete this._events[id]; //delete all traces +}; + + +//debugger helpers +//anything starting from error or log will be removed during code compression + +//add message in the log +dhtmlx.log = function(type,message,details){ + if (window.console && console.log){ + type=type.toLowerCase(); + if (window.console[type]) + window.console[type](message); + else + window.console.log(type +": "+message); + if (details) + window.console.log(details); + } +}; +//register rendering time from call point +dhtmlx.log_full_time = function(name){ + dhtmlx._start_time_log = new Date(); + dhtmlx.log("Info","Timing start ["+name+"]"); + window.setTimeout(function(){ + var time = new Date(); + dhtmlx.log("Info","Timing end ["+name+"]:"+(time.valueOf()-dhtmlx._start_time_log.valueOf())/1000+"s"); + },1); +}; +//register execution time from call point +dhtmlx.log_time = function(name){ + var fname = "_start_time_log"+name; + if (!dhtmlx[fname]){ + dhtmlx[fname] = new Date(); + dhtmlx.log("Info","Timing start ["+name+"]"); + } else { + var time = new Date(); + dhtmlx.log("Info","Timing end ["+name+"]:"+(time.valueOf()-dhtmlx[fname].valueOf())/1000+"s"); + dhtmlx[fname] = null; + } +}; +//log message with type=error +dhtmlx.error = function(message,details){ + dhtmlx.log("Error",message,details); +}; +//event system +dhtmlx.EventSystem={ + _init:function(){ + this._events = {}; //hash of event handlers, name => handler + this._handlers = {}; //hash of event handlers, ID => handler + this._map = {}; + }, + //temporary block event triggering + block : function(){ + this._events._block = true; + }, + //re-enable event triggering + unblock : function(){ + this._events._block = false; + }, + mapEvent:function(map){ + dhtmlx.extend(this._map, map); + }, + //trigger event + callEvent:function(type,params){ + if (this._events._block) return true; + + type = type.toLowerCase(); + dhtmlx.assert_event_call(this, type, params); + + var event_stack =this._events[type.toLowerCase()]; //all events for provided name + var return_value = true; + + if (dhtmlx.debug) //can slowdown a lot + dhtmlx.log("info","["+this.name+"] event:"+type,params); + + if (event_stack) + for(var i=0; i=0) this.splice(pos,(len||1)); + }, + //find element in collection and remove it + remove:function(value){ + this.removeAt(this.find(value)); + }, + //add element to collection at specific position + insertAt:function(data,pos){ + if (!pos && pos!==0) //add to the end by default + this.push(data); + else { + var b = this.splice(pos,(this.length-pos)); + this[pos] = data; + this.push.apply(this,b); //reconstruct array without loosing this pointer + } + }, + //return index of element, -1 if it doesn't exists + find:function(data){ + for (i=0; i0){ + str=this._toHex[number%16]+str; + number=Math.floor(number/16); + } + while (str.length "); + }, + addSector:function(id,alpha0,alpha1,x,y,R,ky){ + var points = []; + points.push(x); + points.push(Math.floor(y*ky)); + for(var i = alpha0; i < alpha1; i+=Math.PI/18){ + points.push(Math.floor(x+R*Math.cos(i))); + points.push(Math.floor((y+R*Math.sin(i))*ky)); + } + points.push(Math.floor(x+R*Math.cos(alpha1))); + points.push(Math.floor((y+R*Math.sin(alpha1))*ky)); + points.push(x); + points.push(Math.floor(y*ky)); + + return this.addPoly(id,points); + }, + render:function(obj){ + var d = dhtmlx.html.create("DIV"); + d.style.cssText="position:absolute; width:100%; height:100%; top:0px; left:0px;"; + obj.appendChild(d); + var src = dhtmlx._isIE?"":"src='data:image/gif;base64,R0lGODlhEgASAIAAAP///////yH5BAUUAAEALAAAAAASABIAAAIPjI+py+0Po5y02ouz3pwXADs='"; + d.innerHTML=""+this._map.join("\n")+""; + + obj._htmlmap = d; //for clearing routine + + this._map = []; + } +}; + + +/* DHX DEPEND FROM FILE 'chart_graph.js'*/ + + +/*DHX:Depend map.js*/ + +if (!dhtmlx.chart) dhtmlx.chart = {}; + +dhtmlx.chart.line = { + + /** + * renders a graphic + * @param: ctx - canvas object + * @param: data - object those need to be displayed + * @param: width - the width of the container + * @param: height - the height of the container + */ + pvt_render_line:function(ctx, data, width, height){ + var maxValue,minValue; + /*necessary if maxValue - minValue < 0*/ + var valueFactor; + /*maxValue - minValue*/ + var relValue; + + + /*necessary to add events and tooltips*/ + var map = new dhtmlx.ui.Map(this._id); + + /*scales*/ + var yax = !!this._settings.yAxis; + var xax = !!this._settings.xAxis; + + if(yax&&(typeof this._settings.yAxis.end!="undefied")&&(typeof this._settings.yAxis.start!="undefied")&&this._settings.yAxis.step){ + maxValue = parseFloat(this._settings.yAxis.end); + minValue = parseFloat(this._settings.yAxis.start); + } + else{ + maxValue = this.max(this._settings.value); + minValue = this.min(this._settings.value); + } + + /*a vertical scale*/ + this._drawYAxis(ctx,data,width,height,minValue,maxValue); + + /*necessary for automatic scale*/ + if(yax){ + maxValue = parseFloat(this._settings.yAxis.end); + minValue = parseFloat(this._settings.yAxis.start); + } + + var topPadding = parseInt(this._settings.padding.top,10); + var leftPadding = parseInt(this._settings.padding.left,10); + var bottomPadding = parseInt(this._settings.padding.bottom,10); + var rightPadding = parseInt(this._settings.padding.right,10); + + /*available height*/ + var total_height = height-topPadding-bottomPadding; + + + /*unit calculation (y_position = value*unit)*/ + var relativeValues = this._getRelativeValue(minValue,maxValue); + relValue = relativeValues[0]; + valueFactor = relativeValues[1]; + var unit = total_height/relValue; + + if(!yax){ + /*defines start value for better representation of small values*/ + var startValue = (unit>10?unit:10); + unit = (total_height-startValue)/relValue; + } + + /*a space available for a single item*/ + var cellWidth = Math.round((width - leftPadding - rightPadding)/data.length); + + /*the value that defines the map area position*/ + var areaPos = Math.floor(cellWidth/2); + + /*drawing all items*/ + if (data.length) { + /*gets the vertical coordinate of an item*/ + var _graph_point = function(data){ + /*the real value of an object*/ + var value = this._settings.value(data); + /*a relative value*/ + var v = (parseFloat(value) - minValue)*valueFactor; + if(!yax) + v += startValue/unit; + /*a vertical coordinate*/ + var y = height - Math.floor(unit*v) - bottomPadding; + /*the limit of the minimum value is the minimum visible value*/ + if(v<0) + y = height - topPadding; + /*the limit of the maximum value*/ + if(value > maxValue) + y = topPadding; + /*the limit of the minimum value*/ + if(value < minValue) + y = height - bottomPadding; + return y; + }; + /*the vertical position of the first item*/ + var y1 = _graph_point.call(this,data[0]); + /*drawing the previous item and the line between to items*/ + for(var i=1; i <= data.length;i ++){ + + + /*horizontal positions of the previous and current items (0.5 - the fix for line width)*/ + var x1 = Math.floor(cellWidth*(i-0.5)) - 0.5 + leftPadding; + var x2 = Math.floor(cellWidth*(i+0.5)) - 0.5 + leftPadding; + + /*sets label on the horizontal scale*/ + this._drawXAxisLabel(x1,data[i-1]); + /*draws a vertical line for the horizontal scale*/ + this._drawXAxisLine(ctx,x1,height-bottomPadding,topPadding); + + /*a line between items*/ + if (data.length!=i){ + var y2 = _graph_point.call(this,data[i]); + this._drawLine(ctx,x1,y1,x2,y2,this._settings.line.color(data[i-1]),this._settings.line.width); + } + + /*draws prevous item*/ + this._drawGraphicItem(ctx,x1,y1,data[i-1]); + + /*creates map area*/ + map.addRect(data[i-1].id,[x1-areaPos,y1-areaPos,x1+areaPos,y1+areaPos]); + + y1=y2; + } + _graph_point = null; + } + /*horizontal scale*/ + this._drawXAxis(ctx,data,width,height); + map.render(this._obj); + }, + /** + * draws an item and its label + * @param: ctx - canvas object + * @param: x0 - the x position of a circle + * @param: y0 - the y position of a circle + * @param: obj - data object + */ + _drawGraphicItem:function(ctx,x0,y0,obj){ + var R = parseInt(this._settings.item.radius,10); + ctx.lineWidth = parseInt(this._settings.item.borderWidth,10); + ctx.fillStyle = this._settings.item.color(obj); + ctx.strokeStyle = this._settings.item.borderColor(obj); + ctx.beginPath(); + ctx.arc(x0,y0,R,0,Math.PI*2,true); + ctx.fill(); + ctx.stroke(); + /*item label*/ + this.renderTextAt(false, true, x0,y0-R-this._settings.labelOffset,this._settings.label(obj)); + } +}; + + +/* DHX DEPEND FROM FILE 'chart_bar.js'*/ + + +/*DHX:Depend map.js*/ + +if (!dhtmlx.chart) dhtmlx.chart = {}; + +dhtmlx.chart.bar = { + /** + * renders a bar chart + * @param: ctx - canvas object + * @param: data - object those need to be displayed + * @param: x - the width of the container + * @param: y - the height of the container + */ + pvt_render_bar:function(ctx, data, x, y){ + var maxValue,minValue; + /*necessary if maxValue - minValue < 0*/ + var valueFactor; + /*maxValue - minValue*/ + var relValue; + + var map = new dhtmlx.ui.Map(this._id); + + var yax = !!this._settings.yAxis; + var xax = !!this._settings.xAxis; + + if(yax&&(typeof this._settings.yAxis.end!="undefied")&&(typeof this._settings.yAxis.start!="undefied")&&this._settings.yAxis.step){ + maxValue = parseFloat(this._settings.yAxis.end); + minValue = parseFloat(this._settings.yAxis.start); + } + else{ + maxValue = this.max(this._settings.value); + minValue = this.min(this._settings.value); + } + + /*a vertical scale*/ + this._drawYAxis(ctx,data,x,y,minValue,maxValue); + + /*necessary for automatic scale*/ + if(yax){ + maxValue = parseFloat(this._settings.yAxis.end); + minValue = parseFloat(this._settings.yAxis.start); + } + + var yPadding = parseInt(this._settings.padding.top,10); + var xPadding = parseInt(this._settings.padding.left,10); + var bottomPadding = parseInt(this._settings.padding.bottom,10); + var total_height = y-yPadding-bottomPadding; + + /*unit calculation (bar_height = value*unit)*/ + var relativeValues = this._getRelativeValue(minValue,maxValue); + relValue = relativeValues[0]; + valueFactor = relativeValues[1]; + + var unit = total_height/relValue; + if(!yax){ + /*defines start value for better representation of small values*/ + var startValue = (unit>10?unit:10); + unit = (total_height-startValue)/relValue; + } + + /*an available width for one bar*/ + var cellWidth = Math.floor((x-xPadding-parseInt(this._settings.padding.right,10))/data.length); + /*a real bar width */ + var barWidth = parseInt(this._settings.width,10); + if(barWidth>cellWidth) barWidth = cellWidth-2; + /*the half of distance between bars*/ + var barOffset = Math.floor((cellWidth - barWidth)/2); + /*the radius of rounding in the top part of each bar*/ + var radius = Math.round(barWidth/5); + + var inner_gradient = false; + var gradient = this._settings.gradient; + + if (gradient === true){ + inner_gradient = true; + gradient = false; + } else if (gradient){ + gradient = ctx.createLinearGradient(0,bottomPadding,0,y-yPadding); + this._settings.gradient(gradient); + } + var scaleY = 0; + /*draws a black line if the horizontal scale isn't defined*/ + if(bottomPadding&&!xax){ + scaleY = y-bottomPadding; + this._drawLine(ctx,0,scaleY+0.5,x,scaleY+0.5,"#000000",1); //hardcoded color! + } + + for(var i=0; i < data.length;i ++){ + + + var value = parseFloat(this._settings.value(data[i])); + if(value>maxValue) value = maxValue; + value -= minValue; + value *= valueFactor; + + /*start point (bottom left)*/ + var x0 = xPadding + barOffset + i*cellWidth; + var y0 = y-bottomPadding; + + + /*sets a label in the horizontal scale*/ + this._drawXAxisLabel(x0+Math.floor(barWidth/2),data[i]); + + if(value<0||(this._settings.yAxis&&value===0)){ + this.renderTextAt(true, true, x0+Math.floor(barWidth/2),y0,this._settings.label(data[i])); + continue; + } + + /*takes start value into consideration*/ + if(!yax) value += startValue/unit; + var color = gradient||this._settings.color.call(this,data[i]); + + /*drawing the gradient border of a bar*/ + if(this._settings.border){ + ctx.beginPath(); + ctx.fillStyle = color; + this._setBarPoints(ctx,x0-1,y0,barWidth+2,radius,unit,value,0); + ctx.lineTo(x0,0); + ctx.fill(); + + ctx.fillStyle = "#000000"; + ctx.globalAlpha = 0.37; + ctx.beginPath(); + this._setBarPoints(ctx,x0-1,y0,barWidth+2,radius,unit,value,0); + ctx.fill(); + } + + /*drawing bar body*/ + ctx.globalAlpha = this._settings.alpha.call(this,data[i]); + ctx.fillStyle = (gradient||this._settings.color.call(this,data[i])); + ctx.beginPath(); + var points = this._setBarPoints(ctx,x0,y0,barWidth,radius,unit,value,(this._settings.border?1:0)); + if (gradient) ctx.lineTo(x0,0); //fix gradient sphreading + ctx.fill(); + ctx.globalAlpha = 1; + + if (inner_gradient){ + var i_gradient = ctx.createLinearGradient(0,y0-unit*value+2,0,y0); + i_gradient.addColorStop(0,color); + i_gradient.addColorStop(0.1,color); + i_gradient.addColorStop(1,"#FFFFFF"); + ctx.fillStyle = i_gradient; + ctx.beginPath(); + var points = this._setBarPoints(ctx,x0+2,y0,barWidth-4,radius,unit,value,1); + ctx.fill(); + } + + + /*sets a bar label*/ + this.renderTextAt(true, true, x0+Math.floor(barWidth/2),points[1],this._settings.label(data[i])); + /*defines a map area for a bar*/ + map.addRect(data[i].id,[x0,points[1],points[0],y0]); + } + + this._drawXAxis(ctx,data,x,y); + map.render(this._obj); + }, + /** + * sets points for bar and returns the position of the bottom right point + * @param: ctx - canvas object + * @param: x0 - the x position of start point + * @param: y0 - the y position of start point + * @param: barWidth - bar width + * @param: radius - the rounding radius of the top + * @param: unit - the value defines the correspondence between item value and bar height + * @param: value - item value + * @param: offset - the offset from expected bar edge (necessary for drawing border) + */ + _setBarPoints:function(ctx,x0,y0,barWidth,radius,unit,value,offset){ + /*correction for displaing small values (when rounding radius is bigger than bar height)*/ + var angle_corr = 0; + if(radius>unit*value){ + var cosA = (radius-unit*value)/radius; + angle_corr = -Math.acos(cosA)+Math.PI/2; + } + /*start*/ + ctx.moveTo(x0,y0); + /*start of left rounding*/ + var y1 = y0 - Math.floor(unit*value) + radius; + if(radiusdetails.total_height)) + y0 += y-details.total_height-ctx.lineWidth/2; + /*considers item index*/ + y0 += i*details.height; + + ctx.moveTo(x0,y0); + var x1 = x0+details.marker.width-details.marker.height +1; + ctx.lineTo(x1,y0); + ctx.stroke(); + + /*item text*/ + this.renderText(x1+details.marker.width/2+5,y0-details.marker.height/2,details.template(obj)); + }, + /** + * returns calculated pie parameters: center position and radius + * @param: x - the width of a container + * @param: y - the height of a container + */ + _getPieParameters:function(x,y){ + var offset = 0; + if(this._settings.legend) + offset = this._settings.legend.width*(this._settings.legend.align=="right"?-1:1); + x = (x + offset)/2; + y = y/2; + var radius = Math.min(x,y)-this._settings.padding.top; + return {"x":x,"y":y,"radius":radius}; + }, + /** + * creates lower part of sector in 3Dpie + * @param: ctx - canvas object + * @param: x0 - the horizontal position of the pie center + * @param: y0 - the vertical position of the pie center + * @param: a0 - the angle that defines the first edge of a sector + * @param: a1 - the angle that defines the second edge of a sector + * @param: R - pie radius + * @param: line (boolean) - if the sector needs a border + */ + _createLowerSector:function(ctx,x0,y0,a1,a2,R,line){ + ctx.lineWidth = 1; + /*checks if the lower sector needs being displayed*/ + if(!((a1<=0 && a2>=0)||(a1>=0 && a2<=Math.PI)||(a1<=Math.PI && a2>=Math.PI))) return; + + if(a1<=0 && a2>=0){ + a1 = 0; + line = false; + this._drawSectorLine(ctx,x0,y0,R,a1,a2); + } + if(a1<=Math.PI && a2>=Math.PI){ + a2 = Math.PI; + line = false; + this._drawSectorLine(ctx,x0,y0,R,a1,a2); + } + /*the height of 3D pie*/ + var offset = (this._settings.height||Math.floor(R/4))/this._settings.cant; + ctx.beginPath(); + ctx.arc(x0,y0,R,a1,a2,false); + ctx.lineTo(x0+R*Math.cos(a2),y0+R*Math.sin(a2)+offset); + ctx.arc(x0,y0+offset,R,a2,a1,true); + ctx.lineTo(x0+R*Math.cos(a1),y0+R*Math.sin(a1)); + ctx.fill(); + if(line) + ctx.stroke(); + }, + /** + * draws a serctor arc + */ + _drawSectorLine:function(ctx,x0,y0,R,a1,a2){ + ctx.beginPath(); + ctx.arc(x0,y0,R,a1,a2,false); + ctx.stroke(); + }, + /** + * adds a shadow to pie + * @param: ctx - canvas object + * @param: x - the horizontal position of the pie center + * @param: y - the vertical position of the pie center + * @param: R - pie radius + */ + _addShadow:function(ctx,x,y,R){ + var shadows = ["#676767","#7b7b7b","#a0a0a0","#bcbcbc","#d1d1d1","#d6d6d6"]; + for(var i = shadows.length-1;i>-1;i--){ + ctx.beginPath(); + ctx.fillStyle = shadows[i]; + ctx.arc(x+2,y+2,R+i,0,Math.PI*2,true); + ctx.fill(); + } + }, + /** + * returns a gray gradient + * @param: gradient - gradient object + */ + _getGrayGradient:function(gradient){ + gradient.addColorStop(0.0,"#ffffff"); + gradient.addColorStop(0.7,"#7a7a7a"); + gradient.addColorStop(1.0,"#000000"); + return gradient; + }, + /** + * adds gray radial gradient + * @param: ctx - canvas object + * @param: x - the horizontal position of the pie center + * @param: y - the vertical position of the pie center + * @param: radius - pie radius + * @param: x0 - the horizontal position of a gradient center + * @param: y0 - the vertical position of a gradient center + */ + _showRadialGradient:function(ctx,x,y,radius,x0,y0){ + ctx.globalAlpha = 0.3; + ctx.beginPath(); + var gradient; + if(typeof this._settings.gradient!= "function"){ + gradient = ctx.createRadialGradient(x0,y0,radius/4,x,y,radius); + gradient = this._getGrayGradient(gradient); + } + else gradient = this._settings.gradient(gradient); + ctx.fillStyle = gradient; + ctx.arc(x,y,radius,0,Math.PI*2,true); + ctx.fill(); + ctx.globalAlpha = 1; + }, + /** + * returns the calculates pie parameters: center position and radius + * @param: ctx - canvas object + * @param: x0 - the horizontal position of the pie center + * @param: y0 - the vertical position of the pie center + * @param: R - pie radius + * @param: alpha1 - the angle that defines the 1st edge of a sector + * @param: alpha2 - the angle that defines the 2nd edge of a sector + * @param: ky - the value that defines an angle of inclination + * @param: text - label text + * @param: in_width (boolean) - if label needs being displayed inside a pie + */ + _drawSectorLabel:function(x0,y0,R,alpha1,alpha2,ky,text,in_width){ + var t = this.renderText(0,0,text,0,1); + if (!t) return; + + //get existing width of text + var labelWidth = t.scrollWidth; + t.style.width = labelWidth+"px"; //adjust text label to fit all text + if (labelWidth>x0) labelWidth = x0; //the text can't be greater than half of view + + //calculate expected correction based on default font metrics + var width = 8; + if (in_width) width = labelWidth/1.8; + var alpha = alpha1+(alpha2-alpha1)/2; + + //calcualteion position and correction + R = R-(width-8)/2; + var corr_x = - width; + var corr_y = -8; + var align = "left"; + + //for items in right upper sector + if(alpha>=Math.PI/2 && alpha=Math.PI){ + corr_x = -labelWidth-corr_x+1; + align = "right"; + } + + //calculate position of text + //basically get point at center of pie sector + var y = (y0+Math.floor(R*Math.sin(alpha)))*ky+corr_y; + var x = x0+Math.floor((R+width/2)*Math.cos(alpha))+corr_x; + + //if pie sector starts in left of right part pie, related text + //must be placed to the left of to the right of pie as well + var left_end = (alpha2 < Math.PI/2+0.01) + var left_start = (alpha < Math.PI/2); + if (left_start && left_end) + x = Math.max(x,x0+3); //right part of pie + else if (!left_start && !left_end) + x = Math.min(x,x0-labelWidth); //left part of pie + + + /*correction for the lower sector of the 3D pie*/ + if (!in_width && ky<1 && y > y0*ky){ + y+= (this._settings.height||Math.floor(R/4)); + } + + //we need to set position of text manually, based on above calculations + t.style.top = y+"px"; + t.style.left = x+"px"; + t.style.width = labelWidth+"px"; + t.style.textAlign = align; + t.style.whiteSpace = "nowrap"; + } +}; + + +/* DHX DEPEND FROM FILE 'template.js'*/ + + +/* + Template - handles html templates +*/ + +/*DHX:Depend dhtmlx.js*/ + +dhtmlx.Template={ + _cache:{ + }, + empty:function(){ + return ""; + }, + setter:function(name, value){ + return dhtmlx.Template.fromHTML(value); + }, + obj_setter:function(name,value){ + var f = dhtmlx.Template.setter(name,value); + var obj = this; + return function(){ + return f.apply(obj, arguments); + }; + }, + fromHTML:function(str){ + if (typeof str == "function") return str; + if (this._cache[str]) + return this._cache[str]; + + //supported idioms + // {obj} => value + // {obj.attr} => named attribute or value of sub-tag in case of xml + // {obj.attr?some:other} conditional output + // {-obj => sub-template + str=(str||"").toString(); + str=str.replace(/[\r\n]+/g,"\\n"); + str=str.replace(/\{obj\.([^}?]+)\?([^:]*):([^}]*)\}/g,"\"+(obj.$1?\"$2\":\"$3\")+\""); + str=str.replace(/\{common\.([^}\(]*)\}/g,"\"+common.$1+\""); + str=str.replace(/\{common\.([^\}\(]*)\(\)\}/g,"\"+(common.$1?common.$1(obj):\"\")+\""); + str=str.replace(/\{obj\.([^}]*)\}/g,"\"+obj.$1+\""); + str=str.replace(/#([a-z0-9_]+)#/gi,"\"+obj.$1+\""); + str=str.replace(/\{obj\}/g,"\"+obj+\""); + str=str.replace(/\{-obj/g,"{obj"); + str=str.replace(/\{-common/g,"{common"); + str="return \""+str+"\";"; + return this._cache[str]= Function("obj","common",str); + } +}; + +dhtmlx.Type={ + /* + adds new template-type + obj - object to which template will be added + data - properties of template + */ + add:function(obj, data){ + //auto switch to prototype, if name of class was provided + if (!obj.types && obj.prototype.types) + obj = obj.prototype; + //if (typeof data == "string") + // data = { template:data }; + + if (dhtmlx.assert_enabled()) + this.assert_event(data); + + var name = data.name||"default"; + + //predefined templates - autoprocessing + this._template(data); + this._template(data,"edit"); + this._template(data,"loading"); + + obj.types[name]=dhtmlx.extend(dhtmlx.extend({},(obj.types[name]||this._default)),data); + return name; + }, + //default template value - basically empty box with 5px margin + _default:{ + css:"default", + template:function(){ return ""; }, + template_edit:function(){ return ""; }, + template_loading:function(){ return "..."; }, + width:150, + height:80, + margin:5, + padding:0 + }, + //template creation helper + _template:function(obj,name){ + name = "template"+(name?("_"+name):""); + var data = obj[name]; + //if template is a string - check is it plain string or reference to external content + if (data && (typeof data == "string")){ + if (data.indexOf("->")!=-1){ + data = data.split("->"); + switch(data[0]){ + case "html": //load from some container on the page + data = dhtmlx.html.getValue(data[1]).replace(/\"/g,"\\\""); + break; + case "http": //load from external file + data = new dhtmlx.ajax().sync().get(data[1],{uid:(new Date()).valueOf()}).responseText; + break; + default: + //do nothing, will use template as is + break; + } + } + obj[name] = dhtmlx.Template.fromHTML(data); + } + } +}; + + + +/* DHX DEPEND FROM FILE 'single_render.js'*/ + + +/* + REnders single item. + Can be used for elements without datastore, or with complex custom rendering logic + + @export + render +*/ + +/*DHX:Depend template.js*/ + +dhtmlx.SingleRender={ + _init:function(){ + }, + //convert item to the HTML text + _toHTML:function(obj){ + /* + this one doesn't support per-item-$template + it has not sense, because we have only single item per object + */ + return this.type._item_start(obj,this.type)+this.type.template(obj,this.type)+this.type._item_end; + }, + //render self, by templating data object + render:function(){ + if (!this.callEvent || this.callEvent("onBeforeRender",[this.data])){ + if (this.data) + this._dataobj.innerHTML = this._toHTML(this.data); + if (this.callEvent) this.callEvent("onAfterRender",[]); + } + } +}; + + +/* DHX DEPEND FROM FILE 'tooltip.js'*/ + + +/* + UI: Tooltip + + @export + show + hide +*/ + +/*DHX:Depend tooltip.css*/ +/*DHX:Depend template.js*/ +/*DHX:Depend single_render.js*/ + +dhtmlx.ui.Tooltip=function(container){ + this.name = "Tooltip"; + this.version = "3.0"; + + if (dhtmlx.assert_enabled()) this._assert(); + + if (typeof container == "string"){ + container = { template:container }; + } + + dhtmlx.extend(this, dhtmlx.Settings); + dhtmlx.extend(this, dhtmlx.SingleRender); + this._parseSettings(container,{ + type:"default", + dy:0, + dx:20 + }); + + //create container for future tooltip + this._dataobj = this._obj = document.createElement("DIV"); + this._obj.className="dhx_tooltip"; + dhtmlx.html.insertBefore(this._obj,document.body.firstChild); +}; +dhtmlx.ui.Tooltip.prototype = { + //show tooptip + //pos - object, pos.x - left, pox.y - top + show:function(data,pos){ + //render sefl only if new data was provided + if (this.data!=data){ + this.data=data; + this.render(data); + } + //show at specified position + this._obj.style.top = pos.y+this._settings.dy+"px"; + this._obj.style.left = pos.x+this._settings.dx+"px"; + this._obj.style.display="block"; + }, + //hide tooltip + hide:function(){ + this.data=null; //nulify, to be sure that on next show it will be fresh-rendered + this._obj.style.display="none"; + }, + types:{ + "default":dhtmlx.Template.fromHTML("{obj.id}") + }, + template_item_start:dhtmlx.Template.empty, + template_item_end:dhtmlx.Template.empty +}; + + + +/* DHX DEPEND FROM FILE 'autotooltip.js'*/ + + +/* + Behavior: AutoTooltip - links tooltip to data driven item +*/ + +/*DHX:Depend tooltip.js*/ + +dhtmlx.AutoTooltip = { + tooltip_setter:function(mode,value){ + var t = new dhtmlx.ui.Tooltip(value); + this.attachEvent("onMouseMove",function(id,e){ //show tooltip on mousemove + t.show(this.get(id),dhtmlx.html.pos(e)); + }); + this.attachEvent("onMouseOut",function(id,e){ //hide tooltip on mouseout + t.hide(); + }); + this.attachEvent("onMouseMoving",function(id,e){ //hide tooltip just after moving start + t.hide(); + }); + return t; + } +}; + + +/* DHX DEPEND FROM FILE 'datastore.js'*/ + + +/*DHX:Depend dhtmlx.js*/ + +/* + DataStore is not a behavior, it standalone object, which represents collection of data. + Call provideAPI to map data API + + @export + exists + idByIndex + indexById + get + set + refresh + dataCount + sort + filter + next + previous + clearAll + first + last +*/ +dhtmlx.DataStore = function(){ + this.name = "DataStore"; + + dhtmlx.extend(this, dhtmlx.EventSystem); + + this.setDriver("xml"); //default data source is an XML + this.pull = {}; //hash of IDs + this.order = dhtmlx.toArray(); //order of IDs +}; + +dhtmlx.DataStore.prototype={ + //defines type of used data driver + //data driver is an abstraction other different data formats - xml, json, csv, etc. + setDriver:function(type){ + dhtmlx.assert(dhtmlx.DataDriver[type],"incorrect DataDriver"); + this.driver = dhtmlx.DataDriver[type]; + }, + //process incoming raw data + _parse:function(data){ + //get size and position of data + var info = this.driver.getInfo(data); + //get array of records + var recs = this.driver.getRecords(data); + + var from = (info._from||0)*1; + var j=0; + for (var i=0; ito){ //can be in case of backward shift-selection + var a=to; to=from; from=a; + } + } + return this.getIndexRange(from,to); + }, + //converts range of indexes to array of all IDs between them + getIndexRange:function(from,to){ + to=Math.min(to,this.dataCount()-1); + + var ret=dhtmlx.toArray(); //result of method is rich-array + for (var i=from; i <= to; i++) + ret.push(this.get(this.order[i])); + return ret; + }, + //returns total count of elements + dataCount:function(){ + return this.order.length; + }, + //returns truy if item with such ID exists + exists:function(id){ + return !!(this.pull[id]); + }, + //nextmethod is not visible on component level, check DataMove.move + //moves item from source index to the target index + move:function(sindex,tindex){ + if (sindex<0 || tindex<0 || tindex >= this.order.length){ + dhtmlx.error("DataStore::move","Incorrect indexes"); + return; + } + + + var id = this.idByIndex(sindex); + var obj = this.get(id); + + this.order.removeAt(sindex); //remove at old position + //if (sindex>tindex) tindex--; //correct shift, caused by element removing + this.order.insertAt(id,tindex); //insert at new position + + //repaint signal + this.callEvent("onStoreUpdated",[id,obj,"move"]); + }, + //adds item to the store + add:function(obj,index){ + //generate id for the item + var id = this.id(obj); + + //by default item is added to the end of the list + var data_size = this.dataCount(); + if (dhtmlx.isNotDefined(index)) + index = data_size; + //check to prevent too big indexes + if (index > data_size){ + dhtmlx.log("Warning","DataStore:add","Index of out of bounds"); + index = Math.min(this.order.length,index); + } + + if (!this.callEvent("onbeforeAdd",[id,index])) return; + + if (this.exists(id)) return dhtmlx.error("Not unique ID"); + + this.pull[id]=obj; + this.order.insertAt(id,index); + if (this._filter_order){ //adding during filtering + //we can't know the location of new item in full dataset, making suggestion + //put at end by default + var original_index = this._filter_order.length; + //put at start only if adding to the start and some data exists + if (!index && this.order.length) + original_index = 0; + + this._filter_order.insertAt(id,original_index); + } + + this.callEvent("onafterAdd",[id,index]); + //repaint signal + this.callEvent("onStoreUpdated",[id,obj,"add"]); + return id; + }, + + //removes element from datastore + remove:function(id){ + //id can be an array of IDs - result of getSelect, for example + if (id instanceof Array){ + for (var i=0; i < id.length; i++) + this.remove(id[i]); + return; + } + if (!this.callEvent("onbeforedelete",[id])) return; + if (!this.exists(id)) return dhtmlx.error("Not existing ID",id); + var obj = this.get(id); //save for later event + //clear from collections + this.order.remove(id); + if (this._filter_order) + this._filter_order.remove(id); + + delete this.pull[id]; + this.callEvent("onafterdelete",[id]); + //repaint signal + this.callEvent("onStoreUpdated",[id,obj,"delete"]); + }, + //deletes all records in datastore + clearAll:function(){ + //instead of deleting one by one - just reset inner collections + this.pull = {}; + this.order = dhtmlx.toArray(); + this._filter_order = null; + this.callEvent("onClearAll",[]); + this.refresh(); + }, + //converts id to index + idByIndex:function(index){ + if (index>=this.order.length || index<0) + dhtmlx.log("Warning","DataStore::idByIndex Incorrect index"); + + return this.order[index]; + }, + //converts index to id + indexById:function(id){ + var res = this.order.find(id); //slower than idByIndex + + if (!res && res!==0) + dhtmlx.log("Warning","DataStore::indexById Non-existing ID: "+ id); + + return res; + }, + //returns ID of next element + next:function(id,step){ + return this.order[this.indexById(id)+(step||1)]; + }, + //returns ID of first element + first:function(){ + return this.order[0]; + }, + //returns ID of last element + last:function(){ + return this.order[this.order.length-1]; + }, + //returns ID of previous element + previous:function(id,step){ + return this.order[this.indexById(id)-(step||1)]; + }, + /* + sort data in collection + by - settings of sorting + + or + + by - sorting function + dir - "asc" or "desc" + + or + + by - property + dir - "asc" or "desc" + as - type of sortings + + Sorting function will accept 2 parameters and must return 1,0,-1, based on desired order + */ + sort:function(by, dir, as){ + + var sort = by; + if (typeof by == "function") + sort = {as:by, dir:dir}; + else if (typeof by == "string") + sort = {by:by, dir:dir, as:as}; + + + var parameters = [sort.by, sort.dir, sort.as]; + if (!this.callEvent("onbeforesort",parameters)) return; + + var sorter = dhtmlx.sort.create(sort); + //get array of IDs + var neworder = this.getRange(); + neworder.sort(sorter); + this.order = neworder.map(function(obj){ return this.id(obj); },this); + + //repaint self + this.refresh(); + + this.callEvent("onaftersort",parameters); + }, + /* + Filter datasource + + text - property, by which filter + value - filter mask + + or + + text - filter method + + Filter method will receive data object and must return true or false + */ + filter:function(text,value){ + //remove previous filtering , if any + if (this._filter_order){ + this.order = this._filter_order; + delete this._filter_order; + } + //if text not define -just unfilter previous state and exit + if (text){ + var filter = text; + if (typeof text == "string"){ + text = dhtmlx.Template.setter(0,text); + filter = function(obj,value){ //default filter - string start from, case in-sensitive + return text(obj).toLowerCase().indexOf(value)!=-1; + }; + } + + value = (value||"").toString().toLowerCase(); + var neworder = dhtmlx.toArray(); + this.order.each(function(id){ + if (filter(this.get(id),value)) + neworder.push(id); + },this); + //set new order of items, store original + this._filter_order = this.order; + this.order = neworder; + } + //repaint self + this.refresh(); + }, + /* + Iterate through collection + */ + each:function(method,master){ + for (var i=0; ib?1:(ab?1:(ab?1:(a max) max = property(obj)*1; + }); + return max; + }, + _split_data_by:function(stats){ + var any=function(property, data){ + property = dhtmlx.Template.setter(0,property); + return property(data[0]); + }; + var key = dhtmlx.Template.setter(0,stats.by); + if (!stats.map[key]) + stats.map[key] = [key, any]; + + var groups = {}; + var labels = []; + this.data.each(function(data){ + var current = key(data); + if (!groups[current]){ + labels.push({id:current}); + groups[current] = dhtmlx.toArray(); + } + groups[current].push(data); + }); + for (var prop in stats.map){ + var functor = (stats.map[prop][1]||any); + if (typeof functor != "function") + functor = this[functor]; + + for (var i=0; i < labels.length; i++) { + labels[i][prop]=functor.call(this, stats.map[prop][0], groups[labels[i].id]); + } + } +// if (this._settings.sort) +// labels.sortBy(stats.sort); + + this._not_grouped_data = this.data; + this.data = new dhtmlx.DataStore(); + this.data.provideApi(this,true); + this._init_group_data_event(this.data, this); + this.parse(labels,"json"); + }, + group:function(config,mode){ + this.ungroup(false); + this._split_data_by(config); + if (mode!==false) + this.render(); + }, + ungroup:function(mode){ + if (this._not_grouped_data){ + this.data = this._not_grouped_data; + this.data.provideApi(this, true); + } + if (mode!==false) + this.render(); + }, + group_setter:function(name, config){ + dhtmlx.assert(typeof config == "object", "Incorrect group value"); + dhtmlx.assert(config.by,"group.by is mandatory"); + dhtmlx.assert(config.map,"group.map is mandatory"); + return config; + }, + //need to be moved to more appropriate object + sort_setter:function(name, config){ + if (typeof config != "object") + config = { by:config }; + + this._mergeSettings(config,{ + as:"string", + dir:"asc" + }); + return config; + } +}; + + +/* DHX DEPEND FROM FILE 'key.js'*/ + + +/* + Behavior:KeyEvents - hears keyboard +*/ +dhtmlx.KeyEvents = { + _init:function(){ + //attach handler to the main container + dhtmlx.event(this._obj,"keypress",this._onKeyPress,this); + }, + //called on each key press , when focus is inside of related component + _onKeyPress:function(e){ + e=e||event; + var code = e.keyCode; //FIXME better solution is required + this.callEvent((this._edit_id?"onEditKeyPress":"onKeyPress"),[code,e.ctrlKey,e.shiftKey,e]); + } +}; + + +/* DHX DEPEND FROM FILE 'mouse.js'*/ + + +/* + Behavior:MouseEvents - provides inner evnets for mouse actions +*/ +dhtmlx.MouseEvents={ + _init: function(){ + //attach dom events if related collection is defined + if (this._click){ + dhtmlx.event(this._obj,"click",this._onClick,this); + dhtmlx.event(this._obj,"contextmenu",this._onContext,this); + } + if (this._dblclick) + dhtmlx.event(this._obj,"dblclick",this._onDblClick,this); + if (this._mouse_move){ + dhtmlx.event(this._obj,"mousemove",this._onMouse,this); + dhtmlx.event(this._obj,(dhtmlx._isIE?"mouseleave":"mouseout"),this._onMouse,this); + } + + }, + //inner onclick object handler + _onClick: function(e) { + return this._mouseEvent(e,this._click,"ItemClick"); + }, + //inner ondblclick object handler + _onDblClick: function(e) { + return this._mouseEvent(e,this._dblclick,"ItemDblClick"); + }, + //process oncontextmenu events + _onContext: function(e) { + var id = dhtmlx.html.locate(e, this._id); + if (id && !this.callEvent("onBeforeContextMenu", [id,e])) + return dhtmlx.html.preventEvent(e); + }, + /* + event throttler - ignore events which occurs too fast + during mouse moving there are a lot of event firing - we need no so much + also, mouseout can fire when moving inside the same html container - we need to ignore such fake calls + */ + _onMouse:function(e){ + if (dhtmlx._isIE) //make a copy of event, will be used in timed call + e = document.createEventObject(event); + + if (this._mouse_move_timer) //clear old event timer + window.clearTimeout(this._mouse_move_timer); + + //this event just inform about moving operation, we don't care about details + this.callEvent("onMouseMoving",[e]); + //set new event timer + this._mouse_move_timer = window.setTimeout(dhtmlx.bind(function(){ + //called only when we have at least 100ms after previous event + if (e.type == "mousemove") + this._onMouseMove(e); + else + this._onMouseOut(e); + },this),500); + }, + //inner mousemove object handler + _onMouseMove: function(e) { + if (!this._mouseEvent(e,this._mouse_move,"MouseMove")) + this.callEvent("onMouseOut",[e||event]); + }, + //inner mouseout object handler + _onMouseOut: function(e) { + this.callEvent("onMouseOut",[e||event]); + }, + //common logic for click and dbl-click processing + _mouseEvent:function(e,hash,name){ + e=e||event; + var trg=e.target||e.srcElement; + var css = ""; + var id = null; + var found = false; + //loop through all parents + while (trg && trg.parentNode){ + if (!found){ //if element with ID mark is not detected yet + id = trg.getAttribute(this._id); //check id of current one + if (id){ + if (!this.callEvent("on"+name,[id,e,trg])) return; //it will be triggered only for first detected ID, in case of nested elements + found = true; //set found flag + } + } + css=trg.className; + if (css){ //check if pre-defined reaction for element's css name exists + css = css.split(" "); + css = css[0]||css[1]; //FIXME:bad solution, workaround css classes which are starting from whitespace + if (hash[css]) + return hash[css].call(this,e,id,trg); + } + trg=trg.parentNode; + } + return found; //returns true if item was located and event was triggered + } +}; + + +/* DHX DEPEND FROM FILE 'config.js'*/ + + +/* + Behavior:Settings + + @export + customize + config +*/ + +/*DHX:Depend template.js*/ +/*DHX:Depend dhtmlx.js*/ + +dhtmlx.Settings={ + _init:function(){ + /* + property can be accessed as this.config.some + in same time for inner call it have sense to use _settings + because it will be minified in final version + */ + this._settings = this.config=[]; + this._settings.sort = null; //mask default method + }, + define:function(property, value){ + if (typeof property == "object") + return this._parseSeetingColl(property); + return this._define(property, value); + }, + _define:function(property,value){ + dhtmlx.assert_settings.call(this,property,value); + + //method with name {prop}_setter will be used as property setter + //setter is optional + var setter = this[property+"_setter"]; + return this._settings[property]=setter?setter.call(this,property,value):value; + }, + //process configuration object + _parseSeetingColl:function(coll){ + if (coll){ + for (var a in coll) //for each setting + this._define(a,coll[a]); //set value through config + } + }, + //helper for object initialization + _parseSettings:function(obj,initial){ + //initial - set of default values + var settings = dhtmlx.extend({},initial); + //code below will copy all properties over default one + if (typeof obj == "object" && !obj.tagName) + dhtmlx.extend(settings,obj); + //call config for each setting + this._parseSeetingColl(settings); + }, + _mergeSettings:function(config, defaults){ + for (var key in defaults) + switch(typeof config[key]){ + case "object": + config[key] = this._mergeSettings((config[key]||{}), defaults[key]); + break; + case "undefined": + config[key] = defaults[key]; + break; + default: //do nothing + break; + } + return config; + }, + //helper for html container init + _parseContainer:function(obj,name,fallback){ + /* + parameter can be a config object, in such case real container will be obj.container + or it can be html object or ID of html object + */ + if (typeof obj == "object" && !obj.tagName) + obj=obj.container; + this._obj = dhtmlx.toNode(obj); + if (!this._obj && fallback) + this._obj = fallback(obj); + + dhtmlx.assert(this._obj, "Incorrect html container"); + + this._obj.className+=" "+name; + this._obj.onselectstart=function(){return false;}; //block selection by default + this._dataobj = this._obj;//separate reference for rendering modules + }, + //apply template-type + _set_type:function(name){ + //parameter can be a hash of settings + if (typeof name == "object") + return this.type_setter("type",name); + + dhtmlx.assert(this.types, "RenderStack :: Types are not defined"); + dhtmlx.assert(this.types[name],"RenderStack :: Inccorect type name",name); + //or parameter can be a name of existing template-type + this.type=dhtmlx.extend({},this.types[name]); + this.customize(); //init configs + }, + customize:function(obj){ + //apply new properties + if (obj) dhtmlx.extend(this.type,obj); + + //init tempaltes for item start and item end + this.type._item_start = dhtmlx.Template.fromHTML(this.template_item_start(this.type)); + this.type._item_end = this.template_item_end(this.type); + + //repaint self + this.render(); + }, + //config.type - creates new template-type, based on configuration object + type_setter:function(mode,value){ + this._set_type(typeof value == "object"?dhtmlx.Type.add(this,value):value); + return value; + }, + //config.template - creates new template-type with defined template string + template_setter:function(mode,value){ + return this.type_setter("type",{template:value}); + }, + //config.css - css name for top level container + css_setter:function(mode,value){ + this._obj.className += " "+value; + return value; + } +}; + + +/* DHX DEPEND FROM FILE 'compatibility.js'*/ + + +/* + Collection of compatibility hacks +*/ + +/*DHX:Depend dhtmlx.js*/ + +dhtmlx.compat=function(name, obj){ + //check if name hach present, and applies it when necessary + if (dhtmlx.compat[name]) + dhtmlx.compat[name](obj); +}; + + +(function(){ + if (!window.dhtmlxError){ + //dhtmlxcommon is not included + + //create fake error tracker for connectors + var dummy = function(){}; + window.dhtmlxError={ catchError:dummy, throwError:dummy }; + //helpers instead of ones from dhtmlxcommon + window.convertStringToBoolean=function(value){ + return !!value; + }; + window.dhtmlxEventable = function(node){ + dhtmlx.extend(node,dhtmlx.EventSystem); + }; + //imitate ajax layer of dhtmlxcommon + var loader = { + getXMLTopNode:function(name){ + + }, + doXPath:function(path){ + return dhtmlx.DataDriver.xml.xpath(this.xml,path); + }, + xmlDoc:{ + responseXML:true + } + }; + //wrap ajax methods of dataprocessor + dhtmlx.compat.dataProcessor=function(obj){ + //FIXME + //this is pretty ugly solution - we replace whole method , so changes in dataprocessor need to be reflected here + + var sendData = "_sendData"; + var in_progress = "_in_progress"; + var tMode = "_tMode"; + var waitMode = "_waitMode"; + + obj[sendData]=function(a1,rowId){ + if (!a1) return; //nothing to send + if (rowId) + this[in_progress][rowId]=(new Date()).valueOf(); + + if (!this.callEvent("onBeforeDataSending",rowId?[rowId,this.getState(rowId)]:[])) return false; + + var a2 = this; + var a3=this.serverProcessor; + if (this[tMode]!="POST") + //use dhtmlx.ajax instead of old ajax layer + dhtmlx.ajax().get(a3+((a3.indexOf("?")!=-1)?"&":"?")+a1,"",function(t,x,xml){ + loader.xml = dhtmlx.DataDriver.xml.checkResponse(t,x); + a2.afterUpdate(a2, null, null, null, loader); + }); + else + dhtmlx.ajax().post(a3,a1,function(t,x,xml){ + loader.xml = dhtmlx.DataDriver.xml.checkResponse(t,x); + a2.afterUpdate(a2, null, null, null, loader); + }); + + this[waitMode]++; + }; + }; + } + +})(); + + +/* DHX DEPEND FROM FILE 'compatibility_layout.js'*/ + + +/*DHX:Depend dhtmlx.js*/ +/*DHX:Depend compatibility.js*/ + +if (!dhtmlx.attaches) + dhtmlx.attaches = {}; + +dhtmlx.attaches.attachAbstract=function(name, conf){ + var obj = document.createElement("DIV"); + obj.id = "CustomObject_"+dhtmlx.uid(); + obj.style.width = "100%"; + obj.style.height = "100%"; + obj.cmp = "grid"; + document.body.appendChild(obj); + this.attachObject(obj.id); + + conf.container = obj.id; + this.grid = new window[name](conf); + + this.gridId = obj.id; + this.gridObj = obj; + return this.grid; +}; +dhtmlx.attaches.attachDataView = function(conf){ + return this.attachAbstract("dhtmlXDataView",conf); +}; +dhtmlx.attaches.attachChart = function(conf){ + return this.attachAbstract("dhtmlXChart",conf); +}; + +dhtmlx.compat.layout = function(){ +if (window.dhtmlXChart) + dhtmlXChart.prototype.setSizes = function(){ + this.resize(); + }; +if (window.dhtmlXDataView) + dhtmlXDataView.prototype.setSizes = function(){ + this.render(); + }; +}; + + +/* DHX DEPEND FROM FILE 'load.js'*/ + + +/* + ajax operations + + can be used for direct loading as + dhtmlx.ajax(ulr, callback) + or + dhtmlx.ajax().get(url) + dhtmlx.ajax().post(url) + +*/ + +/*DHX:Depend datastore.js*/ +/*DHX:Depend dhtmlx.js*/ + +dhtmlx.ajax = function(url,call,master){ + //if parameters was provided - made fast call + if (arguments.length!==0){ + var http_request = new dhtmlx.ajax(); + if (master) http_request.master=master; + http_request.get(url,null,call); + } + if (!this.getXHR) return new dhtmlx.ajax(); //allow to create new instance without direct new declaration + + return this; +}; +dhtmlx.ajax.prototype={ + //creates xmlHTTP object + getXHR:function(){ + if (dhtmlx._isIE) + return new ActiveXObject("Microsoft.xmlHTTP"); + else + return new XMLHttpRequest(); + }, + /* + send data to the server + params - hash of properties which will be added to the url + call - callback, can be an array of functions + */ + send:function(url,params,call){ + var x=this.getXHR(); + if (typeof call == "function") + call = [call]; + //add extra params to the url + if (typeof params == "object"){ + var t=[]; + for (var a in params) + t.push(a+"="+encodeURIComponent(params[a]));// utf-8 escaping + params=t.join("&"); + } + if (params && !this.post){ + url=url+(url.indexOf("?")!=-1 ? "&" : "?")+params; + params=null; + } + + x.open(this.post?"POST":"GET",url,!this._sync); + if (this.post) + x.setRequestHeader('Content-type','application/x-www-form-urlencoded'); + + //async mode, define loading callback + if (!this._sync){ + var self=this; + x.onreadystatechange= function(){ + if (!x.readyState || x.readyState == 4){ + dhtmlx.log_full_time("data_loading"); //log rendering time + if (call && self) + for (var i=0; i < call.length; i++) //there can be multiple callbacks + if (call[i]) + call[i].call((self.master||self),x.responseText,x.responseXML,x); + self.master=null; + call=x=self=null; //anti-leak + } + }; + } + + x.send(params||null); + return x; //return XHR, which can be used in case of sync. mode + }, + //GET request + get:function(url,params,call){ + this.post=false; + return this.send(url,params,call); + }, + //POST request + post:function(url,params,call){ + this.post=true; + return this.send(url,params,call); + }, + sync:function(){ + this._sync = true; + return this; + } +}; + + +/* + Behavior:DataLoader - load data in the component + + @export + load + parse +*/ +dhtmlx.DataLoader={ + _init:function(){ + //prepare data store + this.data = new dhtmlx.DataStore(); + }, + //loads data from external URL + load:function(url,call){ + this.callEvent("onXLS",[]); + if (typeof call == "string"){ //second parameter can be a loading type or callback + this.data.setDriver(call); + call = arguments[2]; + } + //prepare data feed for dyn. loading + if (!this.data.feed) + this.data.feed = function(from,count){ + //allow only single request at same time + if (this._load_count) + return this._load_count=[from,count]; //save last ignored request + else + this._load_count=true; + + this.load(url+((url.indexOf("?")==-1)?"?":"&")+"posStart="+from+"&count="+count,function(){ + //after loading check if we have some ignored requests + var temp = this._load_count; + this._load_count = false; + if (typeof temp =="object") + this.data.feed.apply(this, temp); //load last ignored request + }); + }; + //load data by async ajax call + dhtmlx.ajax(url,[this._onLoad,call],this); + }, + //loads data from object + parse:function(data,type){ + this.callEvent("onXLS",[]); + if (type) + this.data.setDriver(type); + this._onLoad(data,null); + }, + //default after loading callback + _onLoad:function(text,xml,loader){ + this.data._parse(this.data.driver.toObject(text,xml)); + this.callEvent("onXLE",[]); + } +}; + +/* + Abstraction layer for different data types +*/ + +dhtmlx.DataDriver={}; +dhtmlx.DataDriver.json={ + //convert json string to json object if necessary + toObject:function(data){ + if (typeof data == "string"){ + eval ("dhtmlx.temp="+data); + return dhtmlx.temp; + } + return data; + }, + //get array of records + getRecords:function(data){ + if (data && !(data instanceof Array)) + return [data]; + return data; + }, + //get hash of properties for single record + getDetails:function(data){ + return data; + }, + //get count of data and position at which new data need to be inserted + getInfo:function(data){ + return { + _size:(data.total_count||0), + _from:(data.pos||0) + }; + } +}; + +dhtmlx.DataDriver.html={ + /* + incoming data can be + - collection of nodes + - ID of parent container + - HTML text + */ + toObject:function(data){ + if (typeof data == "string"){ + var t=null; + if (data.indexOf("<")==-1) //if no tags inside - probably its an ID + t = dhtmlx.toNode(data); + if (!t){ + t=document.createElement("DIV"); + t.innerHTML = data; + } + + return t.getElementsByTagName(this.tag); + } + return data; + }, + //get array of records + getRecords:function(data){ + if (data.tagName) + return data.childNodes; + return data; + }, + //get hash of properties for single record + getDetails:function(data){ + return dhtmlx.DataDriver.xml.tagToObject(data); + }, + //dyn loading is not supported by HTML data source + getInfo:function(data){ + return { + _size:0, + _from:0 + }; + }, + tag: "LI" +}; + +dhtmlx.DataDriver.jsarray={ + //eval jsarray string to jsarray object if necessary + toObject:function(data){ + if (typeof data == "string"){ + eval ("dhtmlx.temp="+data); + return dhtmlx.temp; + } + return data; + }, + //get array of records + getRecords:function(data){ + return data; + }, + //get hash of properties for single record, in case of array they will have names as "data{index}" + getDetails:function(data){ + var result = {}; + for (var i=0; i < data.length; i++) + result["data"+i]=data[i]; + + return result; + }, + //dyn loading is not supported by js-array data source + getInfo:function(data){ + return { + _size:0, + _from:0 + }; + } +}; + +dhtmlx.DataDriver.csv={ + //incoming data always a string + toObject:function(data){ + return data; + }, + //get array of records + getRecords:function(data){ + return data.split(this.row); + }, + //get hash of properties for single record, data named as "data{index}" + getDetails:function(data){ + data = this.stringToArray(data); + var result = {}; + for (var i=0; i < data.length; i++) + result["data"+i]=data[i]; + + return result; + }, + //dyn loading is not supported by csv data source + getInfo:function(data){ + return { + _size:0, + _from:0 + }; + }, + //split string in array, takes string surrounding quotes in account + stringToArray:function(data){ + data = data.split(this.cell); + for (var i=0; i < data.length; i++) + data[i] = data[i].replace(/^[ \t\n\r]*(\"|)/g,"").replace(/(\"|)[ \t\n\r]*$/g,""); + return data; + }, + row:"\n", //default row separator + cell:"," //default cell separator +}; + +dhtmlx.DataDriver.xml={ + //convert xml string to xml object if necessary + toObject:function(text,xml){ + if (xml && (xml=this.checkResponse(text,xml))) //checkResponse - fix incorrect content type and extra whitespaces errors + return xml; + if (typeof text == "string"){ + return this.fromString(text); + } + return text; + }, + //get array of records + getRecords:function(data){ + return this.xpath(data,this.records); + }, + records:"/*/item", + userdata:"/*/userdata", + //get hash of properties for single record + getDetails:function(data){ + return this.tagToObject(data,{}); + }, + getUserData:function(data,col){ + col = col || {}; + var ud = this.xpath(data,this.userdata); + for (var i=0; i < ud.length; i++) { + var udx = this.tagToObject(ud[i]); + col[udx.name] = udx.value; + } + return col; + }, + //get count of data and position at which new data_loading need to be inserted + getInfo:function(data){ + return { + _size:(data.documentElement.getAttribute("total_count")||0), + _from:(data.documentElement.getAttribute("pos")||0) + }; + }, + //xpath helper + xpath:function(xml,path){ + if (window.XPathResult){ //FF, KHTML, Opera + var node=xml; + if(xml.nodeName.indexOf("document")==-1) + xml=xml.ownerDocument; + var res = []; + var col = xml.evaluate(path, node, null, XPathResult.ANY_TYPE, null); + var temp = col.iterateNext(); + while (temp){ + res.push(temp); + temp = col.iterateNext(); + } + return res; + } //IE + return xml.selectNodes(path); + }, + //convert xml tag to js object, all subtags and attributes are mapped to the properties of result object + tagToObject:function(tag,z){ + z=z||{}; + //map attributes + var a=tag.attributes; + for (var i=0; i5?10:5); + step = parseInt(stepVal,10)*calculStep; + + if(step>Math.abs(nmin)) start = (nmin<0?-step:0); + else{ + + var absNmin = Math.abs(nmin); + var powerStart = Math.floor(this.log10(absNmin)); + var nminVal = absNmin/Math.pow(10,powerStart); + start = Math.ceil(nminVal*10)/10*Math.pow(10,powerStart)-step; + if(nmin<0) start =-start-2*step; + } + var end = start; + while(end<=nmax){ + end += step; + end = parseFloat((new Number(end)).toFixed(Math.abs(power))); + } + return {start:start,end:end,step:step,fixNum:Math.abs(power)}; + }, + log10:function(n){ + return Math.floor((Math.log(n)/Math.LN10)); + }, + _drawXAxisLabel:function(x,obj){ + if (!this._settings.xAxis) return; + var elem = this.renderTextAt(false, true, x, + this._obj.offsetHeight-parseInt(this._settings.padding.bottom,10), + this._settings.xAxis.template(obj)); + }, + _drawXAxisLine:function(ctx,x,y1,y2){ + if (!this._settings.xAxis||!this._settings.xAxis.lines) return; + this._drawLine(ctx,x,y1,x,y2,this._settings.xAxis.color,0.2); + }, + _drawLine:function(ctx,x1,y1,x2,y2,color,width){ + ctx.strokeStyle = color; + ctx.lineWidth = width; + ctx.beginPath(); + ctx.moveTo(x1,y1); + ctx.lineTo(x2,y2); + ctx.stroke(); + }, + _getRelativeValue:function(minValue,maxValue){ + var relValue; + var valueFactor = 1; + if(maxValue != minValue){ + relValue = maxValue - minValue; + if(Math.abs(relValue) < 1){ + while(Math.abs(relValue)<1){ + valueFactor *= 10; + relValue *= valueFactor; + } + } + } + else relValue = minValue; + return [relValue,valueFactor]; + }, + _rainbow : [ + function(pos){ return "#FF"+dhtmlx.math.toHex(pos/2,2)+"00";}, + function(pos){ return "#FF"+dhtmlx.math.toHex(pos/2+128,2)+"00";}, + function(pos){ return "#"+dhtmlx.math.toHex(255-pos,2)+"FF00";}, + function(pos){ return "#00FF"+dhtmlx.math.toHex(pos,2);}, + function(pos){ return "#00"+dhtmlx.math.toHex(255-pos,2)+"FF";}, + function(pos){ return "#"+dhtmlx.math.toHex(pos,2)+"00FF";} + ] +}; + +dhtmlx.compat("layout"); \ No newline at end of file diff --git a/addons/base_graph/static/openerp/js/graph.js b/addons/base_graph/static/openerp/js/graph.js new file mode 100644 index 00000000000..cba7782e82f --- /dev/null +++ b/addons/base_graph/static/openerp/js/graph.js @@ -0,0 +1,71 @@ +/*--------------------------------------------------------- + * OpenERP base_gantt + *---------------------------------------------------------*/ + +openerp.base.graph = function (openerp) { +openerp.base.views.add('graph', 'openerp.base.GraphView'); +openerp.base.GraphView = openerp.base.Controller.extend({ + + init: function(view_manager, session, element_id, dataset, view_id) { + + this._super(session, element_id); + this.view_manager = view_manager; + this.dataset = dataset; + this.model = dataset.model; + this.view_id = view_id; + this.fields_views = {}; + this.widgets = {}; + this.widgets_counter = 0; + this.fields = {}; + this.datarecord = {}; + this.calendar_fields = {}; + }, + do_show: function () { + // TODO: re-trigger search + this.$element.show(); + }, + do_hide: function () { + this.$element.hide(); + }, + start: function() { + this.rpc("/base_graph/graphview/load", {"model": this.model, "view_id": this.view_id}, this.on_loaded); + }, + on_loaded: function(data) { + this.fields_view = data.fields_view; + var self = this; + this.name = this.fields_view.name || this.fields_view.arch.attrs.string; + this.view_id = this.fields_view.view_id; + this.fields['partner_id'] = this.fields_view.arch.children[0].attrs.name; + this.fields['total'] = this.fields_view.arch.children[1].attrs.name; + + console.log("this.fields",this.fields_view); + this.rpc('/base_graph/graphview/get_events', + {'model': this.model, + 'fields': this.fields + }, + function(res) { + self.create_graph(res); + }) + this.$element.html(QWeb.render("GraphView", {"view": this, "fields_view": this.fields_view})); + }, + create_graph: function(res) { + window.onload = function() { + var barChart1 = new dhtmlXChart({ + view: "bar", + container: "chart1", + value: '#partner_id#', + label: '#amount_total#', + width: 30, + gradient: true, + }); + barChart1.parse(res, "json"); + } + }, + +}); + +// here you may tweak globals object, if any, and play with on_* or do_* callbacks on them + +}; + +// vim:et fdc=0 fdl=0: From 20c75c45d8888e44b9b58b8ba67c6b5b2e8e7876 Mon Sep 17 00:00:00 2001 From: "Kunal Chavda (OpenERP)" Date: Fri, 8 Apr 2011 14:20:05 +0530 Subject: [PATCH 02/40] [IMP]Initialy show bar chart with data. bzr revid: kch@tinyerp.com-20110408085005-hv9jv2wcfopnxrgm --- addons/base/static/src/base.html | 6 +- addons/base/static/src/xml/base.xml | 8 +- addons/base_graph/controllers/main.py | 6 +- .../{ => lib}/dhtmlxGraph/License_GPL.html | 0 .../dhtmlxGraph/codebase/dhtmlxchart.css | 0 .../dhtmlxGraph/codebase/dhtmlxchart.js | 0 .../codebase/dhtmlxchart_debug.css | 0 .../dhtmlxGraph/codebase/dhtmlxchart_debug.js | 0 .../codebase/thirdparty/excanvas/AUTHORS | 0 .../codebase/thirdparty/excanvas/COPYING | 0 .../codebase/thirdparty/excanvas/README | 0 .../codebase/thirdparty/excanvas/excanvas.js | 0 .../dhtmlxGraph/dhtmlxchart_full.zip | Bin .../static/{ => lib}/dhtmlxGraph/readme.txt | 0 .../01_initialization/01_load_xml.html | 0 .../01_initialization/02_load_json.html | 0 .../01_initialization/03_load_csv.html | 0 .../01_initialization/04_load_jsarray.html | 0 .../samples/01_initialization/05_series.html | 0 .../samples/02_color/01_default.html | 0 .../samples/02_color/02_custom.html | 0 .../samples/02_color/03_custom_logic.html | 0 .../samples/02_color/04_gradient.html | 0 .../samples/03_group/01_basic.html | 0 .../samples/03_group/02_scales.html | 0 .../samples/04_pie_chart/01_init.html | 0 .../samples/04_pie_chart/02_text.html | 0 .../samples/04_pie_chart/03_3d_chart.html | 0 .../samples/04_pie_chart/04_legend.html | 0 .../samples/05_line_chart/01_init.html | 0 .../samples/05_line_chart/02_style.html | 0 .../samples/05_line_chart/03_scale.html | 0 .../samples/05_line_chart/04_spline.html | 0 .../samples/05_line_chart/05_series.html | 0 .../samples/06_bar_chart/01_init.html | 0 .../samples/06_bar_chart/02_text.html | 0 .../samples/06_bar_chart/03_scales.html | 0 .../samples/06_bar_chart/04_styles.html | 0 .../06_bar_chart/05_stacked_chart.html | 0 .../samples/06_bar_chart/06_series.html | 0 .../06_bar_chart/07_horizonal_bars.html | 0 .../08_horizonal_stacked_bars.html | 0 .../samples/07_area_chart/01_init.html | 0 .../samples/07_area_chart/02_scale.html | 0 .../samples/07_area_chart/03_series.html | 0 .../07_area_chart/03_stacked_area.html | 0 .../samples/08_dynamic/01_add.html | 0 .../samples/08_dynamic/02_events.html | 0 .../samples/08_dynamic/03_sorting.html | 0 .../samples/08_dynamic/04_filtering.html | 0 .../samples/09_integration/01_dhtmlxgrid.html | 0 .../09_integration/02_dhtmlxgrid_group.html | 0 .../samples/09_integration/03_windows.html | 0 .../dhtmlxGraph/samples/common/config.php | 0 .../dhtmlxGraph/samples/common/data.php | 0 .../dhtmlxGraph/samples/common/sales.xml | 0 .../dhtmlxGraph/samples/common/stat.xml | 0 .../{ => lib}/dhtmlxGraph/samples/readme.txt | 0 .../dhtmlxGraph/sources/dhtmlxchart.js | 739 +++++++++--------- .../static/{openerp/js => src}/graph.js | 36 +- 60 files changed, 403 insertions(+), 392 deletions(-) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/License_GPL.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/codebase/dhtmlxchart.css (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/codebase/dhtmlxchart.js (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/codebase/dhtmlxchart_debug.css (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/codebase/dhtmlxchart_debug.js (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/codebase/thirdparty/excanvas/AUTHORS (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/codebase/thirdparty/excanvas/COPYING (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/codebase/thirdparty/excanvas/README (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/codebase/thirdparty/excanvas/excanvas.js (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/dhtmlxchart_full.zip (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/readme.txt (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/01_initialization/01_load_xml.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/01_initialization/02_load_json.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/01_initialization/03_load_csv.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/01_initialization/04_load_jsarray.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/01_initialization/05_series.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/02_color/01_default.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/02_color/02_custom.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/02_color/03_custom_logic.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/02_color/04_gradient.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/03_group/01_basic.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/03_group/02_scales.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/04_pie_chart/01_init.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/04_pie_chart/02_text.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/04_pie_chart/03_3d_chart.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/04_pie_chart/04_legend.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/05_line_chart/01_init.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/05_line_chart/02_style.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/05_line_chart/03_scale.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/05_line_chart/04_spline.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/05_line_chart/05_series.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/06_bar_chart/01_init.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/06_bar_chart/02_text.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/06_bar_chart/03_scales.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/06_bar_chart/04_styles.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/06_bar_chart/05_stacked_chart.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/06_bar_chart/06_series.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/06_bar_chart/07_horizonal_bars.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/06_bar_chart/08_horizonal_stacked_bars.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/07_area_chart/01_init.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/07_area_chart/02_scale.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/07_area_chart/03_series.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/07_area_chart/03_stacked_area.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/08_dynamic/01_add.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/08_dynamic/02_events.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/08_dynamic/03_sorting.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/08_dynamic/04_filtering.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/09_integration/01_dhtmlxgrid.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/09_integration/02_dhtmlxgrid_group.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/09_integration/03_windows.html (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/common/config.php (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/common/data.php (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/common/sales.xml (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/common/stat.xml (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/samples/readme.txt (100%) rename addons/base_graph/static/{ => lib}/dhtmlxGraph/sources/dhtmlxchart.js (92%) rename addons/base_graph/static/{openerp/js => src}/graph.js (79%) diff --git a/addons/base/static/src/base.html b/addons/base/static/src/base.html index a6cff3d9de7..6ba297eef0e 100644 --- a/addons/base/static/src/base.html +++ b/addons/base/static/src/base.html @@ -26,8 +26,8 @@ - - + + @@ -35,7 +35,7 @@ - +