summaryrefslogtreecommitdiff
path: root/addons/base_graph/static/lib/dhtmlxGraph/codebase
diff options
context:
space:
mode:
Diffstat (limited to 'addons/base_graph/static/lib/dhtmlxGraph/codebase')
-rw-r--r--addons/base_graph/static/lib/dhtmlxGraph/codebase/dhtmlxchart.css15
-rw-r--r--addons/base_graph/static/lib/dhtmlxGraph/codebase/dhtmlxchart.js2711
-rw-r--r--addons/base_graph/static/lib/dhtmlxGraph/codebase/dhtmlxchart_debug.css6
-rw-r--r--addons/base_graph/static/lib/dhtmlxGraph/codebase/dhtmlxchart_debug.js4737
-rw-r--r--addons/base_graph/static/lib/dhtmlxGraph/codebase/thirdparty/excanvas/AUTHORS10
-rw-r--r--addons/base_graph/static/lib/dhtmlxGraph/codebase/thirdparty/excanvas/COPYING202
-rw-r--r--addons/base_graph/static/lib/dhtmlxGraph/codebase/thirdparty/excanvas/README22
-rw-r--r--addons/base_graph/static/lib/dhtmlxGraph/codebase/thirdparty/excanvas/excanvas.js927
8 files changed, 8630 insertions, 0 deletions
diff --git a/addons/base_graph/static/lib/dhtmlxGraph/codebase/dhtmlxchart.css b/addons/base_graph/static/lib/dhtmlxGraph/codebase/dhtmlxchart.css
new file mode 100644
index 00000000000..b27bee2b915
--- /dev/null
+++ b/addons/base_graph/static/lib/dhtmlxGraph/codebase/dhtmlxchart.css
@@ -0,0 +1,15 @@
+/*
+Copyright DHTMLX LTD. http://www.dhtmlx.com
+You allowed to use this component or parts of it under GPL terms
+To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlx.com
+*/
+.dhx_tooltip{display:none;position:absolute;font-family:Tahoma;font-size:8pt;z-index:10000;background-color:white;padding:2px 2px 2px 2px;border:1px solid #A4BED4;}
+.dhx_chart{position:relative;font-family:Verdana;font-size:13px;color:#000;overflow:hidden;}
+.dhx_canvas_text{position:absolute;text-align:center;white-space:nowrap;}
+.dhx_map_img{width:100%;height:100%;position:absolute;top:0;left:0;border:0;filter:alpha(opacity=0);}
+.dhx_axis_item_y{position:absolute;height:10px;line-height:10px;text-align:right;}
+.dhx_axis_title_y{text-align:center;font-family:Verdana;-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-o-transform:rotate(-90deg);padding-left:3px;}
+.dhx_axis_item_x{text-align:center;font-size:8pt;-webkit-transform:rotate(-60deg);-moz-transform:rotate(-60deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-o-transform:rotate(-60deg);padding-left:3px;}
+.dhx_axis_title_x{text-align:center;}
+.dhx_chart_legend{position:absolute;}
+.dhx_chart_legend_item{height:18px;line-height:18px;padding:2px;}
diff --git a/addons/base_graph/static/lib/dhtmlxGraph/codebase/dhtmlxchart.js b/addons/base_graph/static/lib/dhtmlxGraph/codebase/dhtmlxchart.js
new file mode 100644
index 00000000000..b00de297737
--- /dev/null
+++ b/addons/base_graph/static/lib/dhtmlxGraph/codebase/dhtmlxchart.js
@@ -0,0 +1,2711 @@
+/*
+Copyright dhtmlxchart LTD. http://www.dhtmlxchart.com
+You allowed to use this component or parts of it under GPL terms
+To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlxchart.com
+*/
+window.dhtmlxchart || (dhtmlxchart = {});
+dhtmlxchart.version = "3.0";
+dhtmlxchart.codebase = "./";
+dhtmlxchart.extend = function (a, b) {
+ for (var c in b) a[c] = b[c];
+ b.k && a.k();
+ return a
+};
+dhtmlxchart.proto_extend = function () {
+ for (var a = arguments, b = a[0], c = [], d = a.length - 1; d > 0; d--) {
+ if (typeof a[d] == "function") a[d] = a[d].prototype;
+ for (var e in a[d]) if (e == "_init") c.push(a[d][e]);
+ else b[e] || (b[e] = a[d][e])
+ }
+ a[0].k && c.push(a[0].k);
+ b.k = function () {
+ for (var g = 0; g < c.length; g++) c[g].apply(this, arguments)
+ };
+ b.base = a[1];
+ var f = function (g) {
+ this.k(g);
+ this.B && this.B(g, this.defaults)
+ };
+ f.prototype = b;
+ b = a = null;
+ return f
+};
+dhtmlxchart.bind = function (a, b) {
+ return function () {
+ return a.apply(b, arguments)
+ }
+};
+dhtmlxchart.require = function (a) {
+ if (!dhtmlxchart.ia[a]) {
+ dhtmlxchart.exec(dhtmlxchart.ajax().sync().get(dhtmlxchart.codebase + a).responseText);
+ dhtmlxchart.ia[a] = true
+ }
+};
+dhtmlxchart.ia = {};
+dhtmlxchart.exec = function (a) {
+ window.execScript ? window.execScript(a) : window.eval(a)
+};
+dhtmlxchart.methodPush = function (a, b) {
+ return function () {
+ var c = false;
+ return c = a[b].apply(a, arguments)
+ }
+};
+dhtmlxchart.isNotDefined = function (a) {
+ return typeof a == "undefined"
+};
+dhtmlxchart.delay = function (a, b, c, d) {
+ setTimeout(function () {
+ var e = a.apply(b, c);
+ a = b = c = null;
+ return e
+ }, d || 1)
+};
+dhtmlxchart.uid = function () {
+ if (!this.S) this.S = (new Date).valueOf();
+ this.S++;
+ return this.S
+};
+dhtmlxchart.toNode = function (a) {
+ if (typeof a == "string") return document.getElementById(a);
+ return a
+};
+dhtmlxchart.toArray = function (a) {
+ return dhtmlxchart.extend(a || [], dhtmlxchart.PowerArray)
+};
+dhtmlxchart.toFunctor = function (a) {
+ return typeof a == "string" ? eval(a) : a
+};
+dhtmlxchart.j = {};
+dhtmlxchart.event = function (a, b, c, d) {
+ a = dhtmlxchart.toNode(a);
+ var e = dhtmlxchart.uid();
+ dhtmlxchart.j[e] = [a, b, c];
+ if (d) c = dhtmlxchart.bind(c, d);
+ if (a.addEventListener) a.addEventListener(b, c, false);
+ else a.attachEvent && a.attachEvent("on" + b, c);
+ return e
+};
+dhtmlxchart.eventRemove = function (a) {
+ if (a) {
+ var b = dhtmlxchart.j[a];
+ if (b[0].removeEventListener) b[0].removeEventListener(b[1], b[2], false);
+ else b[0].detachEvent && b[0].detachEvent("on" + b[1], b[2]);
+ delete this.j[a]
+ }
+};
+dhtmlxchart.EventSystem = {
+ k: function () {
+ this.j = {};
+ this.A = {};
+ this.s = {}
+ },
+ block: function () {
+ this.j.V = true
+ },
+ unblock: function () {
+ this.j.V = false
+ },
+ mapEvent: function (a) {
+ dhtmlxchart.extend(this.s, a)
+ },
+ callEvent: function (a, b) {
+ if (this.j.V) return true;
+ a = a.toLowerCase();
+ var c = this.j[a.toLowerCase()],
+ d = true;
+ if (c) for (var e = 0; e < c.length; e++) if (c[e].apply(this, b || []) === false) d = false;
+ if (this.s[a] && !this.s[a].callEvent(a, b)) d = false;
+ return d
+ },
+ attachEvent: function (a, b, c) {
+ a = a.toLowerCase();
+ c = c || dhtmlxchart.uid();
+ b = dhtmlxchart.toFunctor(b);
+ var d = this.j[a] || dhtmlxchart.toArray();
+ d.push(b);
+ this.j[a] = d;
+ this.A[c] = {
+ f: b,
+ t: a
+ };
+ return c
+ },
+ detachEvent: function (a) {
+ var b = this.A[a].t,
+ c = this.A[a].f;
+ b = this.j[b];
+ b.remove(c);
+ delete this.A[a]
+ }
+};
+dhtmlxchart.PowerArray = {
+ removeAt: function (a, b) {
+ if (a >= 0) this.splice(a, b || 1)
+ },
+ remove: function (a) {
+ this.removeAt(this.find(a))
+ },
+ insertAt: function (a, b) {
+ if (!b && b !== 0) this.push(a);
+ else {
+ var c = this.splice(b, this.length - b);
+ this[b] = a;
+ this.push.apply(this, c)
+ }
+ },
+ find: function (a) {
+ for (i = 0; i < this.length; i++) if (a == this[i]) return i;
+ return -1
+ },
+ each: function (a, b) {
+ for (var c = 0; c < this.length; c++) a.call(b || this, this[c])
+ },
+ map: function (a, b) {
+ for (var c = 0; c < this.length; c++) this[c] = a.call(b || this, this[c]);
+ return this
+ }
+};
+dhtmlxchart.env = {};
+if (navigator.userAgent.indexOf("Opera") != -1) dhtmlxchart.Ma = true;
+else {
+ dhtmlxchart.r = !! document.all;
+ dhtmlxchart.La = !document.all;
+ dhtmlxchart.Na = navigator.userAgent.indexOf("KHTML") != -1;
+ if (navigator.appVersion.indexOf("MSIE 8.0") != -1 && document.compatMode != "BackCompat") dhtmlxchart.r = 8
+}
+dhtmlxchart.env = {};
+(function () {
+ dhtmlxchart.env.transform = false;
+ dhtmlxchart.env.transition = false;
+ var a = {};
+ a.names = ["transform", "transition"];
+ a.transform = ["transform", "WebkitTransform", "MozTransform", "oTransform"];
+ a.transition = ["transition", "WebkitTransition", "MozTransition", "oTransition"];
+ for (var b = document.createElement("DIV"), c = 0; c < a.names.length; c++) for (; p = a[a.names[c]].pop();) if (typeof b.style[p] != "undefined") dhtmlxchart.env[a.names[c]] = true
+})();
+dhtmlxchart.env.transform_prefix = function () {
+ var a;
+ if (dhtmlxchart.Ma) a = "-o-";
+ else {
+ a = "";
+ if (dhtmlxchart.La) a = "-moz-";
+ if (dhtmlxchart.Na) a = "-webkit-"
+ }
+ return a
+}();
+dhtmlxchart.env.svg = function () {
+ return document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")
+}();
+dhtmlxchart.zIndex = {
+ drag: 1E4
+};
+dhtmlxchart.html = {
+ create: function (a, b, c) {
+ b = b || {};
+ var d = document.createElement(a);
+ for (var e in b) d.setAttribute(e, b[e]);
+ if (b.style) d.style.cssText = b.style;
+ if (b["class"]) d.className = b["class"];
+ if (c) d.innerHTML = c;
+ return d
+ },
+ getValue: function (a) {
+ a = dhtmlxchart.toNode(a);
+ if (!a) return "";
+ return dhtmlxchart.isNotDefined(a.value) ? a.innerHTML : a.value
+ },
+ remove: function (a) {
+ if (a instanceof Array) for (var b = 0; b < a.length; b++) this.remove(a[b]);
+ else a && a.parentNode && a.parentNode.removeChild(a)
+ },
+ insertBefore: function (a, b, c) {
+ if (a) b ? b.parentNode.insertBefore(a, b) : c.appendChild(a)
+ },
+ locate: function (a, b) {
+ a = a || event;
+ for (var c = a.target || a.srcElement; c;) {
+ if (c.getAttribute) {
+ var d = c.getAttribute(b);
+ if (d) return d
+ }
+ c = c.parentNode
+ }
+ return null
+ },
+ offset: function (a) {
+ if (a.getBoundingClientRect) {
+ var b = a.getBoundingClientRect(),
+ c = document.body,
+ d = document.documentElement,
+ e = window.pageYOffset || d.scrollTop || c.scrollTop,
+ f = window.pageXOffset || d.scrollLeft || c.scrollLeft,
+ g = d.clientTop || c.clientTop || 0,
+ i = d.clientLeft || c.clientLeft || 0,
+ j = b.top + e - g,
+ k = b.left + f - i;
+ return {
+ y: Math.round(j),
+ x: Math.round(k)
+ }
+ } else {
+ for (k = j = 0; a;) {
+ j += parseInt(a.offsetTop, 10);
+ k += parseInt(a.offsetLeft, 10);
+ a = a.offsetParent
+ }
+ return {
+ y: j,
+ x: k
+ }
+ }
+ },
+ pos: function (a) {
+ a = a || event;
+ if (a.pageX || a.pageY) return {
+ x: a.pageX,
+ y: a.pageY
+ };
+ var b = dhtmlxchart.r && document.compatMode != "BackCompat" ? document.documentElement : document.body;
+ return {
+ x: a.clientX + b.scrollLeft - b.clientLeft,
+ y: a.clientY + b.scrollTop - b.clientTop
+ }
+ },
+ preventEvent: function (a) {
+ a && a.preventDefault && a.preventDefault();
+ dhtmlxchart.html.stopEvent(a)
+ },
+ stopEvent: function (a) {
+ (a || event).cancelBubble = true;
+ return false
+ },
+ addCss: function (a, b) {
+ a.className += " " + b
+ },
+ removeCss: function (a, b) {
+ a.className = a.className.replace(RegExp(b, "g"), "")
+ }
+};
+(function () {
+ var a = document.getElementsByTagName("SCRIPT");
+ if (a.length) {
+ a = (a[a.length - 1].getAttribute("src") || "").split("/");
+ a.splice(a.length - 1, 1);
+ dhtmlxchart.codebase = a.slice(0, a.length).join("/") + "/"
+ }
+})();
+dhtmlxchart.ui = {};
+dhtmlxchart.Destruction = {
+ k: function () {
+ dhtmlxchart.destructors.push(this)
+ },
+ destructor: function () {
+ this.destructor = function () {};
+ this.ib = this.v = null;
+ this.ga && document.body.appendChild(this.ga);
+ this.ga = null;
+ if (this.g) {
+ this.g.innerHTML = "";
+ this.g.v = null
+ }
+ this.data = this.g = this.L = null;
+ this.j = this.A = {}
+ }
+};
+dhtmlxchart.destructors = [];
+dhtmlxchart.event(window, "unload", function () {
+ for (var a = 0; a < dhtmlxchart.destructors.length; a++) dhtmlxchart.destructors[a].destructor();
+ dhtmlxchart.destructors = [];
+ for (var b in dhtmlxchart.j) {
+ a = dhtmlxchart.j[b];
+ if (a[0].removeEventListener) a[0].removeEventListener(a[1], a[2], false);
+ else a[0].detachEvent && a[0].detachEvent("on" + a[1], a[2]);
+ delete dhtmlxchart.j[b]
+ }
+});
+dhtmlxchart.math = {};
+dhtmlxchart.math.gb = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];
+dhtmlxchart.math.toHex = function (a, b) {
+ a = parseInt(a, 10);
+ for (str = ""; a > 0;) {
+ str = this.gb[a % 16] + str;
+ a = Math.floor(a / 16)
+ }
+ for (; str.length < b;) str = "0" + str;
+ return str
+};
+dhtmlxchart.ui.Map = function (a) {
+ this.name = "Map";
+ this.q = "map_" + dhtmlxchart.uid();
+ this.Qa = a;
+ this.s = []
+};
+dhtmlxchart.ui.Map.prototype = {
+ addRect: function (a, b, c) {
+ this.Y(a, "RECT", b, c)
+ },
+ addPoly: function (a, b) {
+ this.Y(a, "POLY", b)
+ },
+ Y: function (a, b, c, d) {
+ var e = "";
+ if (arguments.length == 4) e = "userdata='" + d + "'";
+ this.s.push("<area " + this.Qa + "='" + a + "' shape='" + b + "' coords='" + c.join() + "' " + e + "></area>")
+ },
+ addSector: function (a, b, c, d, e, f, g) {
+ var i = [];
+ i.push(d);
+ i.push(Math.floor(e * g));
+ for (var j = b; j < c; j += Math.PI / 18) {
+ i.push(Math.floor(d + f * Math.cos(j)));
+ i.push(Math.floor((e + f * Math.sin(j)) * g))
+ }
+ i.push(Math.floor(d + f * Math.cos(c)));
+ i.push(Math.floor((e + f * Math.sin(c)) * g));
+ i.push(d);
+ i.push(Math.floor(e * g));
+ return this.addPoly(a, i)
+ },
+ render: function (a) {
+ var b = dhtmlxchart.html.create("DIV");
+ b.style.cssText = "position:absolute; width:100%; height:100%; top:0px; left:0px;";
+ a.appendChild(b);
+ var c = dhtmlxchart.r ? "" : "src='data:image/gif;base64,R0lGODlhEgASAIAAAP///////yH5BAUUAAEALAAAAAASABIAAAIPjI+py+0Po5y02ouz3pwXADs='";
+ b.innerHTML = "<map id='" + this.q + "' name='" + this.q + "'>" + this.s.join("\n") + "</map><img " + c + " class='dhx_map_img' usemap='#" + this.q + "'>";
+ a.v = b;
+ this.s = []
+ }
+};
+dhtmlxchart.chart = {};
+dhtmlxchart.chart.area = {
+ pvt_render_area: function (a, b, c, d, e, f) {
+ var g = this.C(a, b, c, d, e),
+ i = Math.floor(g.cellWidth / 2);
+ if (b.length) {
+ a.globalAlpha = this.e.alpha.call(this, b[0]);
+ a.fillStyle = this.e.color.call(this, b[0]);
+ var j = this.p(b[0], c, d, g),
+ k = this.e.offset ? c.x + g.cellWidth * 0.5 : c.x;
+ a.beginPath();
+ a.moveTo(k, d.y);
+ a.lineTo(k, j);
+ f.addRect(b[0].id, [k - i, j - i, k + i, j + i]);
+ this.e.yAxis || this.renderTextAt(false, !this.e.offset ? false : true, k, j - this.e.labelOffset, this.e.label(b[0]));
+ for (var h = 1; h < b.length; h++) {
+ var m = k + Math.floor(g.cellWidth * h) - 0.5,
+ l = this.p(b[h], c, d, g);
+ a.lineTo(m, l);
+ f.addRect(b[h].id, [m - i, l - i, m + i, l + i]);
+ this.e.yAxis || this.renderTextAt(false, !this.e.offset && h == b.length - 1 ? "left" : "center", m, l - this.e.labelOffset, this.e.label(b[h]))
+ }
+ a.lineTo(k + Math.floor(g.cellWidth * [b.length - 1]), d.y);
+ a.lineTo(k, d.y);
+ a.fill()
+ }
+ }
+};
+dhtmlxchart.chart.stackedArea = {
+ pvt_render_stackedArea: function (a, b, c, d, e, f) {
+ var g = this.C(a, b, c, d, e),
+ i = Math.floor(g.cellWidth / 2),
+ j = [];
+ if (b.length) {
+ a.globalAlpha = this.e.alpha.call(this, b[0]);
+ a.fillStyle = this.e.color.call(this, b[0]);
+ var k = e ? b[0].$startY : d.y,
+ h = this.e.offset ? c.x + g.cellWidth * 0.5 : c.x,
+ m = this.p(b[0], c, d, g) - (e ? d.y - k : 0);
+ j[0] = m;
+ a.beginPath();
+ a.moveTo(h, k);
+ a.lineTo(h, m);
+ f.addRect(b[0].id, [h - i, m - i, h + i, m + i]);
+ this.e.yAxis || this.renderTextAt(false, true, h, m - this.e.labelOffset, this.e.label(b[0]));
+ for (var l = 1; l < b.length; l++) {
+ var n = h + Math.floor(g.cellWidth * l) - 0.5,
+ o = this.p(b[l], c, d, g) - (e ? d.y - b[l].$startY : 0);
+ j[l] = o;
+ a.lineTo(n, o);
+ f.addRect(b[l].id, [n - i, o - i, n + i, o + i]);
+ this.e.yAxis || this.renderTextAt(false, true, n, o - this.e.labelOffset, this.e.label(b[l]))
+ }
+ a.lineTo(h + Math.floor(g.cellWidth * [b.length - 1]), k);
+ if (e) for (l = b.length - 1; l >= 0; l--) {
+ n = h + Math.floor(g.cellWidth * l) - 0.5;
+ var s = b[l].$startY;
+ a.lineTo(n, s)
+ } else a.lineTo(h + Math.floor(g.cellWidth * (length - 1)) - 0.5, k);
+ a.lineTo(h, k);
+ a.fill();
+ for (l = 0; l < b.length; l++) b[l].$startY = j[l]
+ }
+ }
+};
+dhtmlxchart.chart.spline = {
+ pvt_render_spline: function (a, b, c, d, e) {
+ var f = this.C(a, b, c, d, e);
+ Math.floor(f.cellWidth / 2);
+ var g = [];
+ if (b.length) {
+ var i = this.e.offset ? c.x + f.cellWidth * 0.5 : c.x;
+ for (e = 0; e < b.length; e++) {
+ var j = !e ? i : Math.floor(f.cellWidth * e) - 0.5 + i,
+ k = this.p(b[e], c, d, f);
+ g.push({
+ x: j,
+ y: k
+ })
+ }
+ var h = this.Ia(g);
+ for (e = 0; e < g.length - 1; e++) {
+ var m = g[e].x;
+ c = g[e].y;
+ for (var l = g[e + 1].x, n = g[e + 1].y, o = m; o < l; o++) this.i(a, o, this.P(o, m, e, h.a, h.b, h.c, h.d), o + 1, this.P(o + 1, m, e, h.a, h.b, h.c, h.d), this.e.line.color(b[e]), this.e.line.width);
+ this.i(a, l - 1, this.P(o, m, e, h.a, h.b, h.c, h.d), l, n, this.e.line.color(b[e]), this.e.line.width);
+ this.M(a, m, c, b[e], this.e.label(b[e]))
+ }
+ this.M(a, l, n, b[e], this.e.label(b[e]))
+ }
+ },
+ Ia: function (a) {
+ var b, c, d, e, f, g, i, j, k;
+ b = [];
+ m = [];
+ k = a.length;
+ for (var h = 0; h < k - 1; h++) {
+ b[h] = a[h + 1].x - a[h].x;
+ m[h] = (a[h + 1].y - a[h].y) / b[h]
+ }
+ c = [];
+ d = [];
+ c[0] = 0;
+ c[1] = 2 * (b[0] + b[1]);
+ d[0] = 0;
+ d[1] = 6 * (m[1] - m[0]);
+ for (h = 2; h < k - 1; h++) {
+ c[h] = 2 * (b[h - 1] + b[h]) - b[h - 1] * b[h - 1] / c[h - 1];
+ d[h] = 6 * (m[h] - m[h - 1]) - b[h - 1] * d[h - 1] / c[h - 1]
+ }
+ e = [];
+ e[k - 1] = e[0] = 0;
+ for (h = k - 2; h >= 1; h--) e[h] = (d[h] - b[h] * e[h + 1]) / c[h];
+ f = [];
+ g = [];
+ i = [];
+ j = [];
+ for (h = 0; h < k - 1; h++) {
+ f[h] = a[h].y;
+ g[h] = -b[h] * e[h + 1] / 6 - b[h] * e[h] / 3 + (a[h + 1].y - a[h].y) / b[h];
+ i[h] = e[h] / 2;
+ j[h] = (e[h + 1] - e[h]) / (6 * b[h])
+ }
+ return {
+ a: f,
+ b: g,
+ c: i,
+ d: j
+ }
+ },
+ P: function (a, b, c, d, e, f, g) {
+ return d[c] + (a - b) * (e[c] + (a - b) * (f[c] + (a - b) * g[c]))
+ }
+};
+dhtmlxchart.chart.barH = {
+ pvt_render_barH: function (a, b, c, d, e, f) {
+ var g, i, j, k, h = d.x - c.x,
+ m = !! this.e.yAxis,
+ l = this.O("h");
+ g = l.max;
+ i = l.min;
+ var n = Math.floor((d.y - c.y) / b.length);
+ e || this.aa(a, b, c, d, i, g, n);
+ if (m) {
+ g = parseFloat(this.e.xAxis.end);
+ i = parseFloat(this.e.xAxis.start)
+ }
+ var o = this.z(i, g);
+ k = o[0];
+ j = o[1];
+ var s = k ? h / k : 10;
+ if (!m) {
+ var t = 10;
+ s = k ? (h - t) / k : 10
+ }
+ var q = parseInt(this.e.width, 10);
+ if (q * this.h.length + 4 > n) q = n / this.h.length - 4;
+ var v = Math.floor((n - q * this.h.length) / 2),
+ p = typeof this.e.radius != "undefined" ? parseInt(this.e.radius, 10) : Math.round(q / 5),
+ u = false,
+ r = this.e.gradient;
+ if (r && typeof r != "function") {
+ u = r;
+ r = false
+ } else if (r) {
+ r = a.createLinearGradient(c.x, c.y, d.x, c.y);
+ this.e.gradient(r)
+ }
+ m || this.i(a, c.x - 0.5, c.y, c.x - 0.5, d.y, "#000000", 1);
+ for (d = 0; d < b.length; d++) {
+ var w = parseFloat(this.e.value(b[d]));
+ if (w > g) w = g;
+ w -= i;
+ w *= j;
+ var x = c.x,
+ y = c.y + v + d * n + (q + 1) * e;
+ if (w < 0 || this.e.yAxis && w === 0) this.renderTextAt("middle", true, x + 10, y + q / 2 + v, this.e.label(b[d]));
+ else {
+ m || (w += t / s);
+ var B = r || this.e.color.call(this, b[d]);
+ if (this.e.border) {
+ a.beginPath();
+ a.fillStyle = B;
+ this.o(a, x, y, q, p, s, w, 0);
+ a.lineTo(x, 0);
+ a.fill();
+ a.fillStyle = "#000000";
+ a.globalAlpha = 0.37;
+ a.beginPath();
+ this.o(a, x, y, q, p, s, w, 0);
+ a.fill()
+ }
+ a.globalAlpha = this.e.alpha.call(this, b[d]);
+ a.fillStyle = r || this.e.color.call(this, b[d]);
+ a.beginPath();
+ var z = this.o(a, x, y, q, p, s, w, this.e.border ? 1 : 0);
+ if (r && !u) a.lineTo(c.x + h, y + (this.e.border ? 1 : 0));
+ a.fill();
+ a.globalAlpha = 1;
+ if (u != false) {
+ var A = this.G(a, c.x, y + q, c.x + s * w + 2, y, u, B, "x");
+ a.fillStyle = A.gradient;
+ a.beginPath();
+ z = this.o(a, x, y + A.offset, q - A.offset * 2, p, s, w, A.offset);
+ a.fill();
+ a.globalAlpha = 1
+ }
+ this.renderTextAt("middle", false, z[0] + 3, parseInt(y + (z[1] - y) / 2, 10), this.e.label(b[d]));
+ f.addRect(b[d].id, [x, y, z[0], z[1]], e)
+ }
+ }
+ },
+ o: function (a, b, c, d, e, f, g, i) {
+ var j = 0;
+ if (e > f * g) {
+ var k = (e - f * g) / e;
+ j = -Math.asin(k) + Math.PI / 2
+ }
+ a.moveTo(b, c + i);
+ var h = b + f * g - e - (e ? 0 : i);
+ e < f * g && a.lineTo(h, c + i);
+ f = c + e;
+ e && a.arc(h, f, e - i, -Math.PI / 2 + j, 0, false);
+ var m = c + d - e - (e ? 0 : i),
+ l = h + e - (e ? i : 0);
+ a.lineTo(l, m);
+ var n = h;
+ e && a.arc(n, m, e - i, 0, Math.PI / 2 - j, false);
+ var o = c + d - i;
+ a.lineTo(b, o);
+ a.lineTo(b, c + i);
+ return [l, o]
+ },
+ aa: function (a, b, c, d, e, f, g) {
+ this.ya(a, b, c, d, e, f);
+ this.za(a, b, c, d, g)
+ },
+ za: function (a, b, c, d, e) {
+ if (this.e.yAxis) {
+ var f = c.x - 0.5,
+ g = d.y + 0.5,
+ i = c.y;
+ this.i(a, f, g, f, i, this.e.yAxis.color, 1);
+ for (a = 0; a < b.length; a++) this.renderTextAt("middle", 0, 0, i + e / 2 + a * e, this.e.yAxis.template(b[a]), "dhx_axis_item_y", c.x - 5);
+ this.pa(c, d)
+ }
+ },
+ ya: function (a, b, c, d, e, f) {
+ var g, i = {},
+ j = this.e.xAxis;
+ if (j) {
+ b = d.y + 0.5;
+ var k = c.x - 0.5,
+ h = d.x - 0.5;
+ this.i(a, k, b, h, b, j.color, 1);
+ if (j.step) g = parseFloat(j.step);
+ if (typeof j.step == "undefined" || typeof j.start == "undefined" || typeof j.end == "undefined") {
+ i = this.W(e, f);
+ e = i.start;
+ f = i.end;
+ g = i.step;
+ this.e.xAxis.end = f;
+ this.e.xAxis.start = e;
+ this.e.xAxis.step = g
+ }
+ if (g !== 0) {
+ for (var m = (h - k) * g / (f - e), l = 0, n = e; n <= f; n += g) {
+ if (i.fixNum) n = parseFloat((new Number(n)).toFixed(i.fixNum));
+ var o = Math.floor(k + l * m) + 0.5;
+ n != e && j.lines && this.i(a, o, b, o, c.y, this.e.xAxis.color, 0.2);
+ this.renderTextAt(false, true, o, b + 2, j.template(n.toString()), "dhx_axis_item_x");
+ l++
+ }
+ this.renderTextAt(true, false, k, d.y + this.e.padding.bottom - 3, this.e.xAxis.title, "dhx_axis_title_x", d.x - c.x);
+ j.lines && this.i(a, k, c.y - 0.5, h, c.y - 0.5, this.e.xAxis.color, 0.2)
+ }
+ }
+ }
+};
+dhtmlxchart.chart.stackedBarH = {
+ pvt_render_stackedBarH: function (a, b, c, d, e, f) {
+ var g, i, j, k, h = d.x - c.x,
+ m = !! this.e.yAxis;
+ i = this.Q(b);
+ g = i.max;
+ i = i.min;
+ var l = Math.floor((d.y - c.y) / b.length);
+ e || this.aa(a, b, c, d, i, g, l);
+ if (m) {
+ g = parseFloat(this.e.xAxis.end);
+ i = parseFloat(this.e.xAxis.start)
+ }
+ j = this.z(i, g);
+ k = j[0];
+ j = j[1];
+ var n = k ? h / k : 10;
+ if (!m) {
+ var o = 10;
+ n = k ? (h - o) / k : 10
+ }
+ k = parseInt(this.e.width, 10);
+ if (k + 4 > l) k = l - 4;
+ var s = Math.floor((l - k) / 2),
+ t = 0,
+ q = false,
+ v = this.e.gradient;
+ q = false;
+ if (v = this.e.gradient) q = true;
+ m || this.i(a, c.x - 0.5, c.y, c.x - 0.5, d.y, "#000000", 1);
+ for (d = 0; d < b.length; d++) {
+ if (!e) b[d].$startX = c.x;
+ var p = parseFloat(this.e.value(b[d]));
+ if (p > g) p = g;
+ p -= i;
+ p *= j;
+ var u = c.x,
+ r = c.y + s + d * l;
+ if (e) u = b[d].$startX;
+ if (p < 0 || this.e.yAxis && p === 0) this.renderTextAt("middle", true, u + 10, r + k / 2, this.e.label(b[d]));
+ else {
+ m || (p += o / n);
+ var w = this.e.color.call(this, b[d]);
+ if (this.e.border) {
+ a.beginPath();
+ a.fillStyle = w;
+ this.o(a, u, r, k, t, n, p, 0);
+ a.lineTo(u, 0);
+ a.fill();
+ a.fillStyle = "#000000";
+ a.globalAlpha = 0.37;
+ a.beginPath();
+ this.o(a, u, r, k, t, n, p, 0);
+ a.fill()
+ }
+ a.globalAlpha = 1;
+ a.globalAlpha = this.e.alpha.call(this, b[d]);
+ a.fillStyle = this.e.color.call(this, b[d]);
+ a.beginPath();
+ var x = this.o(a, u, r, k, t, n, p, this.e.border ? 1 : 0);
+ if (v && !q) a.lineTo(c.x + h, r + (this.e.border ? 1 : 0));
+ a.fill();
+ if (q != false) {
+ w = this.G(a, u, r + k, u, r, q, w, "x");
+ a.fillStyle = w.gradient;
+ a.beginPath();
+ x = this.o(a, u, r, k, t, n, p, 0);
+ a.fill();
+ a.globalAlpha = 1
+ }
+ this.renderTextAt("middle", true, b[d].$startX + (x[0] - b[d].$startX) / 2 - 1, r + (x[1] - r) / 2, this.e.label(b[d]));
+ f.addRect(b[d].id, [b[d].$startX, r, x[0], x[1]], e);
+ b[d].$startX = x[0]
+ }
+ }
+ }
+};
+dhtmlxchart.chart.stackedBar = {
+ pvt_render_stackedBar: function (a, b, c, d, e, f) {
+ var g, i, j, k = d.y - c.y;
+ j = !! this.e.yAxis;
+ var h = !! this.e.xAxis;
+ i = this.Q(b);
+ g = i.max;
+ i = i.min;
+ var m = Math.floor((d.x - c.x) / b.length);
+ e || this.N(a, b, c, d, i, g, m);
+ if (j) {
+ g = parseFloat(this.e.yAxis.end);
+ i = parseFloat(this.e.yAxis.start)
+ }
+ g = this.z(i, g);
+ j = g[0];
+ g = g[1];
+ j = j ? k / j : 10;
+ var l = parseInt(this.e.width, 10);
+ if (l + 4 > m) l = m - 4;
+ var n = Math.floor((m - l) / 2),
+ o = this.e.gradient ? this.e.gradient : false;
+ h || this.i(a, c.x, d.y + 0.5, d.x, d.y + 0.5, "#000000", 1);
+ for (h = 0; h < b.length; h++) {
+ var s = parseFloat(this.e.value(b[h]));
+ if (s) {
+ e || (s -= i);
+ s *= g;
+ var t = c.x + n + h * m,
+ q = d.y;
+ if (e) q = b[h].$startY;
+ if (!(q < c.y + 1)) if (s < 0 || this.e.yAxis && s === 0) this.renderTextAt(true, true, t + Math.floor(l / 2), q, this.e.label(b[h]));
+ else {
+ var v = this.e.color.call(this, b[h]);
+ if (this.e.border) {
+ a.beginPath();
+ a.fillStyle = v;
+ this.I(a, t - 1, q, l + 2, j, s, 0, c.y);
+ a.lineTo(t, q);
+ a.fill();
+ a.fillStyle = "#000000";
+ a.globalAlpha = 0.37;
+ a.beginPath();
+ this.I(a, t - 1, q, l + 2, j, s, 0, c.y);
+ a.fill()
+ }
+ a.globalAlpha = this.e.alpha.call(this, b[h]);
+ a.fillStyle = this.e.color.call(this, b[h]);
+ a.beginPath();
+ var p = this.I(a, t, q, l, j, s, this.e.border ? 1 : 0, c.y);
+ a.fill();
+ a.globalAlpha = 1;
+ if (o) {
+ v = this.G(a, t, q, t + l, p[1], o, v, "y");
+ a.fillStyle = v.gradient;
+ a.beginPath();
+ p = this.I(a, t + v.offset, q, l - v.offset * 2, j, s, this.e.border ? 1 : 0, c.y);
+ a.fill();
+ a.globalAlpha = 1
+ }
+ this.renderTextAt(false, true, t + Math.floor(l / 2), p[1] + (q - p[1]) / 2 - 7, this.e.label(b[h]));
+ f.addRect(b[h].id, [t, p[1], p[0], b[h].$startY || q], e);
+ b[h].$startY = this.e.border ? p[1] + 1 : p[1]
+ }
+ }
+ }
+ },
+ I: function (a, b, c, d, e, f, g, i) {
+ a.moveTo(b, c);
+ f = c - e * f + g;
+ if (f < i) f = i;
+ a.lineTo(b, f);
+ e = b + d;
+ f = f;
+ a.lineTo(e, f);
+ var j = b + d;
+ a.lineTo(j, c);
+ a.lineTo(b, c);
+ return [j, f - 2 * g]
+ }
+};
+dhtmlxchart.chart.line = {
+ pvt_render_line: function (a, b, c, d, e, f) {
+ var g = this.C(a, b, c, d, e),
+ i = Math.floor(g.cellWidth / 2);
+ if (b.length) for (var j = this.p(b[0], c, d, g), k = this.e.offset ? c.x + g.cellWidth * 0.5 : c.x, h = k, m = 1; m <= b.length; m++) {
+ var l = Math.floor(g.cellWidth * m) - 0.5 + h;
+ if (b.length != m) {
+ var n = this.p(b[m], c, d, g);
+ this.i(a, k, j, l, n, this.e.line.color(b[m - 1]), this.e.line.width)
+ }
+ this.M(a, k, j, b[m - 1], !! this.e.offset);
+ f.addRect(b[m - 1].id, [k - i, j - i, k + i, j + i], e);
+ j = n;
+ k = l
+ }
+ },
+ M: function (a, b, c, d, e) {
+ var f = parseInt(this.e.item.radius, 10);
+ a.lineWidth = parseInt(this.e.item.borderWidth, 10);
+ a.fillStyle = this.e.item.color(d);
+ a.strokeStyle = this.e.item.borderColor(d);
+ a.beginPath();
+ a.arc(b, c, f, 0, Math.PI * 2, true);
+ a.fill();
+ a.stroke();
+ e && this.renderTextAt(false, true, b, c - f - this.e.labelOffset, this.e.label(d))
+ },
+ p: function (a, b, c, d) {
+ var e = d.minValue,
+ f = d.maxValue,
+ g = d.unit,
+ i = d.valueFactor;
+ a = this.e.value(a);
+ i = (parseFloat(a) - e) * i;
+ this.e.yAxis || (i += d.startValue / g);
+ d = c.y - Math.floor(g * i);
+ if (i < 0) d = c.y;
+ if (a > f) d = b.y;
+ if (a < e) d = c.y;
+ return d
+ },
+ C: function (a, b, c, d, e) {
+ var f = {};
+ f.totalHeight = d.y - c.y;
+ f.cellWidth = Math.round((d.x - c.x) / (!this.e.offset ? b.length - 1 : b.length));
+ var g = !! this.e.yAxis,
+ i = this.e.view.indexOf("stacked") != -1 ? this.Q(b) : this.O();
+ f.maxValue = i.max;
+ f.minValue = i.min;
+ e || this.N(a, b, c, d, f.minValue, f.maxValue, f.cellWidth);
+ if (g) {
+ f.maxValue = parseFloat(this.e.yAxis.end);
+ f.minValue = parseFloat(this.e.yAxis.start)
+ }
+ b = this.z(f.minValue, f.maxValue);
+ a = b[0];
+ f.valueFactor = b[1];
+ f.unit = a ? f.totalHeight / a : 10;
+ f.startValue = 0;
+ if (!g) {
+ f.startValue = f.unit > 10 ? f.unit : 10;
+ f.unit = a ? (f.totalHeight - f.startValue) / a : 10
+ }
+ return f
+ }
+};
+dhtmlxchart.chart.bar = {
+ pvt_render_bar: function (a, b, c, d, e, f) {
+ var g, i, j, k, h = d.y - c.y,
+ m = !! this.e.yAxis,
+ l = !! this.e.xAxis;
+ i = this.O();
+ g = i.max;
+ i = i.min;
+ var n = Math.floor((d.x - c.x) / b.length);
+ !e && !(this.e.origin != "auto" && !m) && this.N(a, b, c, d, i, g, n);
+ if (m) {
+ g = parseFloat(this.e.yAxis.end);
+ i = parseFloat(this.e.yAxis.start)
+ }
+ j = this.z(i, g);
+ k = j[0];
+ j = j[1];
+ var o = k ? h / k : k;
+ if (!m && !(this.e.origin != "auto" && l)) {
+ var s = 10;
+ o = k ? (h - s) / k : s
+ }!e && this.e.origin != "auto" && !m && this.e.origin > i && this.ea(a, b, c, d, n, d.y - o * (this.e.origin - i));
+ h = parseInt(this.e.width, 10);
+ if (this.h && h * this.h.length + 4 > n) h = n / this.h.length - 4;
+ k = Math.floor((n - h * this.h.length) / 2);
+ var t = typeof this.e.radius != "undefined" ? parseInt(this.e.radius, 10) : Math.round(h / 5),
+ q = false,
+ v = this.e.gradient;
+ if (v && typeof v != "function") {
+ q = v;
+ v = false
+ } else if (v) {
+ v = a.createLinearGradient(0, d.y, 0, c.y);
+ this.e.gradient(v)
+ }
+ l || this.i(a, c.x, d.y + 0.5, d.x, d.y + 0.5, "#000000", 1);
+ for (var p = 0; p < b.length; p++) {
+ var u = parseFloat(this.e.value(b[p]));
+ if (u > g) u = g;
+ u -= i;
+ u *= j;
+ var r = c.x + k + p * n + (h + 1) * e,
+ w = d.y;
+ if (u < 0 || this.e.yAxis && u === 0 && !(this.e.origin != "auto" && this.e.origin > i)) this.renderTextAt(true, true, r + Math.floor(h / 2), w, this.e.label(b[p]));
+ else {
+ if (!m && !(this.e.origin != "auto" && l)) u += s / o;
+ var x = v || this.e.color.call(this, b[p]);
+ this.e.border && this.wa(a, r, w, h, i, t, o, u, x);
+ a.globalAlpha = this.e.alpha.call(this, b[p]);
+ var y = this.va(a, c, r, w, h, i, t, o, u, x, v, q);
+ a.globalAlpha = 1;
+ q && this.xa(a, r, w, h, i, t, o, u, x, q);
+ y[0] != r ? this.renderTextAt(false, true, r + Math.floor(h / 2), y[1], this.e.label(b[p])) : this.renderTextAt(true, true, r + Math.floor(h / 2), y[3], this.e.label(b[p]));
+ f.addRect(b[p].id, [r, y[3], y[2], y[1]], e)
+ }
+ }
+ },
+ K: function (a, b, c, d, e, f, g) {
+ var i = this.e.xAxis,
+ j = c;
+ if (i && this.e.origin != "auto" && this.e.origin > g) {
+ c -= (this.e.origin - g) * e;
+ j = c;
+ d -= this.e.origin - g;
+ if (d < 0) {
+ d *= -1;
+ a.translate(b + f, c);
+ a.rotate(Math.PI);
+ c = b = 0
+ }
+ c -= 0.5
+ }
+ return {
+ value: d,
+ x0: b,
+ y0: c,
+ start: j
+ }
+ },
+ va: function (a, b, c, d, e, f, g, i, j, k, h, m) {
+ a.save();
+ a.fillStyle = k;
+ var l = this.K(a, c, d, j, i, e, f);
+ e = this.H(a, l.x0, l.y0, e, g, i, l.value, this.e.border ? 1 : 0);
+ if (h && !m) a.lineTo(l.x0 + (this.e.border ? 1 : 0), b.y);
+ a.fill();
+ a.restore();
+ a = l.x0;
+ b = l.x0 != c ? c + e[0] : e[0];
+ d = l.x0 != c ? l.start - e[1] : d;
+ c = l.x0 != c ? l.start : e[1];
+ return [a, d, b, c]
+ },
+ wa: function (a, b, c, d, e, f, g, i, j) {
+ a.save();
+ b = this.K(a, b, c, i, g, d, e);
+ a.fillStyle = j;
+ this.H(a, b.x0, b.y0, d, f, g, b.value, 0);
+ a.lineTo(b.x0, 0);
+ a.fill();
+ a.fillStyle = "#000000";
+ a.globalAlpha = 0.37;
+ this.H(a, b.x0, b.y0, d, f, g, b.value, 0);
+ a.fill();
+ a.restore()
+ },
+ xa: function (a, b, c, d, e, f, g, i, j, k) {
+ a.save();
+ b = this.K(a, b, c, i, g, d, e);
+ j = this.G(a, b.x0, b.y0, b.x0 + d, b.y0 - g * b.value + 2, k, j, "y");
+ a.fillStyle = j.gradient;
+ this.H(a, b.x0 + j.offset, b.y0, d - j.offset * 2, f, g, b.value, j.offset);
+ a.fill();
+ a.restore()
+ },
+ H: function (a, b, c, d, e, f, g, i) {
+ a.beginPath();
+ var j = 0;
+ if (e > f * g) {
+ var k = (e - f * g) / e;
+ j = -Math.acos(k) + Math.PI / 2
+ }
+ a.moveTo(b + i, c);
+ var h = c - Math.floor(f * g) + e + (e ? 0 : i);
+ e < f * g && a.lineTo(b + i, h);
+ f = b + e;
+ e && a.arc(f, h, e - i, -Math.PI + j, -Math.PI / 2, false);
+ g = b + d - e - (e ? 0 : i);
+ f = h - e + (e ? i : 0);
+ a.lineTo(g, f);
+ h = h;
+ e && a.arc(g, h, e - i, -Math.PI / 2, 0 - j, false);
+ d = b + d - i;
+ a.lineTo(d, c);
+ a.lineTo(b + i, c);
+ return [d, f]
+ }
+};
+dhtmlxchart.chart.pie = {
+ pvt_render_pie: function (a, b, c, d, e, f) {
+ this.oa(a, b, c, d, 1, f)
+ },
+ oa: function (a, b, c, d, e, f) {
+ var g = 0,
+ i = this.Ha(c, d);
+ c = this.e.radius ? this.e.radius : i.radius;
+ this.max(this.e.value);
+ for (var j = [], k = [], h = 0, m = 0; m < b.length; m++) g += parseFloat(this.e.value(b[m]));
+ for (m = 0; m < b.length; m++) {
+ k[m] = parseFloat(this.e.value(b[m]));
+ j[m] = Math.PI * 2 * (g ? (k[m] + h) / g : 1 / b.length);
+ h += k[m]
+ }
+ d = this.e.x ? this.e.x : i.x;
+ var l = this.e.y ? this.e.y : i.y;
+ e == 1 && this.e.shadow && this.ta(a, d, l, c);
+ l /= e;
+ var n = -Math.PI / 2;
+ a.scale(1, e);
+ for (m = 0; m < b.length; m++) if (k[m]) {
+ a.lineWidth = 2;
+ a.beginPath();
+ a.moveTo(d, l);
+ alpha1 = -Math.PI / 2 + j[m] - 1.0E-4;
+ a.arc(d, l, c, n, alpha1, false);
+ a.lineTo(d, l);
+ var o = this.e.color.call(this, b[m]);
+ a.fillStyle = o;
+ a.strokeStyle = this.e.lineColor(b[m]);
+ a.stroke();
+ a.fill();
+ this.e.pieInnerText && this.ca(d, l, 5 * c / 6, n, alpha1, e, this.e.pieInnerText(b[m], g), true);
+ this.e.label && this.ca(d, l, c + this.e.labelOffset, n, alpha1, e, this.e.label(b[m]));
+ if (e != 1) {
+ this.X(a, d, l, n, alpha1, c, true);
+ a.fillStyle = "#000000";
+ a.globalAlpha = 0.2;
+ this.X(a, d, l, n, alpha1, c, false);
+ a.globalAlpha = 1;
+ a.fillStyle = o
+ }
+ f.addSector(b[m].id, n, alpha1, d, l, c, e);
+ n = alpha1
+ }
+ if (this.e.gradient) {
+ b = e != 1 ? d + c / 3 : d;
+ f = e != 1 ? l + c / 3 : l;
+ this.cb(a, d, l, c, b, f)
+ }
+ a.scale(1, 1 / e)
+ },
+ Ha: function (a, b) {
+ var c = b.x - a.x,
+ d = b.y - a.y;
+ b = a.x + c / 2;
+ a = a.y + d / 2;
+ var e = Math.min(c / 2, d / 2);
+ return {
+ x: b,
+ y: a,
+ radius: e
+ }
+ },
+ X: function (a, b, c, d, e, f, g) {
+ a.lineWidth = 1;
+ if (d <= 0 && e >= 0 || d >= 0 && e <= Math.PI || d <= Math.PI && e >= Math.PI) {
+ if (d <= 0 && e >= 0) {
+ d = 0;
+ g = false;
+ this.da(a, b, c, f, d, e)
+ }
+ if (d <= Math.PI && e >= Math.PI) {
+ e = Math.PI;
+ g = false;
+ this.da(a, b, c, f, d, e)
+ }
+ var i = (this.e.height || Math.floor(f / 4)) / this.e.cant;
+ a.beginPath();
+ a.arc(b, c, f, d, e, false);
+ a.lineTo(b + f * Math.cos(e), c + f * Math.sin(e) + i);
+ a.arc(b, c + i, f, e, d, true);
+ a.lineTo(b + f * Math.cos(d), c + f * Math.sin(d));
+ a.fill();
+ g && a.stroke()
+ }
+ },
+ da: function (a, b, c, d, e, f) {
+ a.beginPath();
+ a.arc(b, c, d, e, f, false);
+ a.stroke()
+ },
+ ta: function (a, b, c, d) {
+ for (var e = ["#676767", "#7b7b7b", "#a0a0a0", "#bcbcbc", "#d1d1d1", "#d6d6d6"], f = e.length - 1; f > -1; f--) {
+ a.beginPath();
+ a.fillStyle = e[f];
+ a.arc(b + 2, c + 2, d + f, 0, Math.PI * 2, true);
+ a.fill()
+ }
+ },
+ Ga: function (a) {
+ a.addColorStop(0, "#ffffff");
+ a.addColorStop(0.7, "#7a7a7a");
+ a.addColorStop(1, "#000000");
+ return a
+ },
+ cb: function (a, b, c, d, e, f) {
+ a.globalAlpha = 0.3;
+ a.beginPath();
+ var g;
+ if (typeof this.e.gradient != "function") {
+ g = a.createRadialGradient(e, f, d / 4, b, c, d);
+ g = this.Ga(g)
+ } else g = this.e.gradient(g);
+ a.fillStyle = g;
+ a.arc(b, c, d, 0, Math.PI * 2, true);
+ a.fill();
+ a.globalAlpha = 1
+ },
+ ca: function (a, b, c, d, e, f, g, i) {
+ var j = this.renderText(0, 0, g, 0, 1);
+ if (j) {
+ var k = j.scrollWidth;
+ j.style.width = k + "px";
+ if (k > a) k = a;
+ var h = 8;
+ if (i) h = k / 1.8;
+ var m = d + (e - d) / 2;
+ c -= (h - 8) / 2;
+ var l = -h,
+ n = -8,
+ o = "left";
+ if (m >= Math.PI / 2 && m < Math.PI) {
+ l = -k - l + 1;
+ o = "right"
+ }
+ if (m <= 3 * Math.PI / 2 && m >= Math.PI) {
+ l = -k - l + 1;
+ o = "right"
+ }
+ d = (b + Math.floor(c * Math.sin(m))) * f + n;
+ h = a + Math.floor((c + h / 2) * Math.cos(m)) + l;
+ var s = e < Math.PI / 2 + 0.01,
+ t = m < Math.PI / 2;
+ if (t && s) h = Math.max(h, a + 3);
+ else if (!t && !s) h = Math.min(h, a - k);
+ if (!i && f < 1 && d > b * f) d += this.e.height || Math.floor(c / 4);
+ j.style.top = d + "px";
+ j.style.left = h + "px";
+ j.style.width = k + "px";
+ j.style.textAlign = o;
+ j.style.whiteSpace = "nowrap"
+ }
+ }
+};
+dhtmlxchart.chart.pie3D = {
+ pvt_render_pie3D: function (a, b, c, d, e, f) {
+ this.oa(a, b, c, d, this.e.cant, f)
+ }
+};
+dhtmlxchart.Template = {
+ J: {},
+ empty: function () {
+ return ""
+ },
+ setter: function (a, b) {
+ return dhtmlxchart.Template.fromHTML(b)
+ },
+ obj_setter: function (a, b) {
+ var c = dhtmlxchart.Template.setter(a, b),
+ d = this;
+ return function () {
+ return c.apply(d, arguments)
+ }
+ },
+ fromHTML: function (a) {
+ if (typeof a == "function") return a;
+ if (this.J[a]) return this.J[a];
+ a = (a || "").toString();
+ a = a.replace(/[\r\n]+/g, "\\n");
+ a = a.replace(/\{obj\.([^}?]+)\?([^:]*):([^}]*)\}/g, '"+(obj.$1?"$2":"$3")+"');
+ a = a.replace(/\{common\.([^}\(]*)\}/g, '"+common.$1+"');
+ a = a.replace(/\{common\.([^\}\(]*)\(\)\}/g, '"+(common.$1?common.$1(obj):"")+"');
+ a = a.replace(/\{obj\.([^}]*)\}/g, '"+obj.$1+"');
+ a = a.replace(/#([a-z0-9_]+)#/gi, '"+obj.$1+"');
+ a = a.replace(/\{obj\}/g, '"+obj+"');
+ a = a.replace(/\{-obj/g, "{obj");
+ a = a.replace(/\{-common/g, "{common");
+ a = 'return "' + a + '";';
+ return this.J[a] = Function("obj", "common", a)
+ }
+};
+dhtmlxchart.Type = {
+ add: function (a, b) {
+ if (!a.types && a.prototype.types) a = a.prototype;
+ var c = b.name || "default";
+ this.T(b);
+ this.T(b, "edit");
+ this.T(b, "loading");
+ a.types[c] = dhtmlxchart.extend(dhtmlxchart.extend({}, a.types[c] || this.ua), b);
+ return c
+ },
+ ua: {
+ css: "default",
+ template: function () {
+ return ""
+ },
+ template_edit: function () {
+ return ""
+ },
+ template_loading: function () {
+ return "..."
+ },
+ width: 150,
+ height: 80,
+ margin: 5,
+ padding: 0
+ },
+ T: function (a, b) {
+ b = "template" + (b ? "_" + b : "");
+ var c = a[b];
+ if (c && typeof c == "string") {
+ if (c.indexOf("->") != -1) {
+ c = c.split("->");
+ switch (c[0]) {
+ case "html":
+ c = dhtmlxchart.html.getValue(c[1]).replace(/\"/g, '\\"');
+ break;
+ case "http":
+ c = (new dhtmlxchart.ajax).sync().get(c[1], {
+ uid: (new Date).valueOf()
+ }).responseText;
+ break;
+ default:
+ break
+ }
+ }
+ a[b] = dhtmlxchart.Template.fromHTML(c)
+ }
+ }
+};
+dhtmlxchart.SingleRender = {
+ k: function () {},
+ fb: function (a) {
+ return this.type.Pa(a, this.type) + this.type.template(a, this.type) + this.type.Oa
+ },
+ render: function () {
+ if (!this.callEvent || this.callEvent("onBeforeRender", [this.data])) {
+ if (this.data) this.L.innerHTML = this.fb(this.data);
+ this.callEvent && this.callEvent("onAfterRender", [])
+ }
+ }
+};
+dhtmlxchart.ui.Tooltip = function (a) {
+ this.name = "Tooltip";
+ this.version = "3.0";
+ if (typeof a == "string") a = {
+ template: a
+ };
+ dhtmlxchart.extend(this, dhtmlxchart.Settings);
+ dhtmlxchart.extend(this, dhtmlxchart.SingleRender);
+ this.B(a, {
+ type: "default",
+ dy: 0,
+ dx: 20
+ });
+ this.L = this.g = document.createElement("DIV");
+ this.g.className = "dhx_tooltip";
+ dhtmlxchart.html.insertBefore(this.g, document.body.firstChild)
+};
+dhtmlxchart.ui.Tooltip.prototype = {
+ show: function (a, b) {
+ if (!this.$) {
+ if (this.data != a) {
+ this.data = a;
+ this.render(a)
+ }
+ this.g.style.top = b.y + this.e.dy + "px";
+ this.g.style.left = b.x + this.e.dx + "px";
+ this.g.style.display = "block"
+ }
+ },
+ hide: function () {
+ this.data = null;
+ this.g.style.display = "none"
+ },
+ disable: function () {
+ this.$ = true
+ },
+ enable: function () {
+ this.$ = false
+ },
+ types: {
+ "default": dhtmlxchart.Template.fromHTML("{obj.id}")
+ },
+ template_item_start: dhtmlxchart.Template.empty,
+ template_item_end: dhtmlxchart.Template.empty
+};
+dhtmlxchart.AutoTooltip = {
+ tooltip_setter: function (a, b) {
+ var c = new dhtmlxchart.ui.Tooltip(b);
+ this.attachEvent("onMouseMove", function (d, e) {
+ c.show(this.get(d), dhtmlxchart.html.pos(e))
+ });
+ this.attachEvent("onMouseOut", function () {
+ c.hide()
+ });
+ this.attachEvent("onMouseMoving", function () {
+ c.hide()
+ });
+ return c
+ }
+};
+dhtmlxchart.DataStore = function () {
+ this.name = "DataStore";
+ dhtmlxchart.extend(this, dhtmlxchart.EventSystem);
+ this.setDriver("xml");
+ this.pull = {};
+ this.order = dhtmlxchart.toArray();
+ this.sa = false
+};
+dhtmlxchart.DataStore.prototype = {
+ setDriver: function (a) {
+ this.driver = dhtmlxchart.DataDriver[a]
+ },
+ ra: function (a) {
+ if (a.item) {
+ if (!(a.item instanceof Array)) a.item = [a.item];
+ for (var b = 0; b < a.item.length; b++) {
+ var c = a.item[b],
+ d = this.id(c);
+ a.item[b] = d;
+ this.pull[d] = c;
+ c.parent = a.id;
+ c.level = a.level + 1;
+ this.ra(c)
+ }
+ }
+ },
+ Xa: function (a) {
+ for (var b = this.driver.getInfo(a), c = this.driver.getRecords(a), d = (b.u || 0) * 1, e = 0, f = 0; f < c.length; f++) {
+ var g = this.driver.getDetails(c[f]),
+ i = this.id(g);
+ if (!this.pull[i]) {
+ this.order[e + d] = i;
+ e++
+ }
+ this.pull[i] = g;
+ if (this.sa) {
+ g.level = 1;
+ this.ra(g)
+ }
+ }
+ for (f = 0; f < b.w; f++) if (!this.order[f]) {
+ i = dhtmlxchart.uid();
+ g = {
+ id: i,
+ $template: "loading"
+ };
+ this.pull[i] = g;
+ this.order[f] = i
+ }
+ this.callEvent("onStoreLoad", [this.driver, a]);
+ this.refresh()
+ },
+ id: function (a) {
+ return a.id || (a.id = dhtmlxchart.uid())
+ },
+ get: function (a) {
+ return this.pull[a]
+ },
+ set: function (a, b) {
+ this.pull[a] = b;
+ this.refresh()
+ },
+ refresh: function (a) {
+ a ? this.callEvent("onStoreUpdated", [a, this.pull[a], "update"]) : this.callEvent("onStoreUpdated", [null, null, null])
+ },
+ getRange: function (a, b) {
+ if (arguments.length) {
+ a = this.indexById(a);
+ b = this.indexById(b);
+ if (a > b) {
+ var c = b;
+ b = a;
+ a = c
+ }
+ } else {
+ a = this.min || 0;
+ b = Math.min(this.max || Infinity, this.dataCount() - 1)
+ }
+ return this.getIndexRange(a, b)
+ },
+ getIndexRange: function (a, b) {
+ b = Math.min(b, this.dataCount() - 1);
+ var c = dhtmlxchart.toArray();
+ for (a = a; a <= b; a++) c.push(this.get(this.order[a]));
+ return c
+ },
+ dataCount: function () {
+ return this.order.length
+ },
+ exists: function (a) {
+ return !!this.pull[a]
+ },
+ move: function (a, b) {
+ if (!(a < 0 || b < 0)) {
+ var c = this.idByIndex(a),
+ d = this.get(c);
+ this.order.removeAt(a);
+ this.order.insertAt(c, Math.min(this.order.length, b));
+ this.callEvent("onStoreUpdated", [c, d, "move"])
+ }
+ },
+ add: function (a, b) {
+ var c = this.id(a),
+ d = this.dataCount();
+ if (dhtmlxchart.isNotDefined(b) || b < 0) b = d;
+ if (b > d) b = Math.min(this.order.length, b);
+ if (this.callEvent("onbeforeAdd", [c, b])) {
+ if (this.exists(c)) return null;
+ this.pull[c] = a;
+ this.order.insertAt(c, b);
+ if (this.m) {
+ var e = this.m.length;
+ if (!b && this.order.length) e = 0;
+ this.m.insertAt(c, e)
+ }
+ this.callEvent("onafterAdd", [c, b]);
+ this.callEvent("onStoreUpdated", [c, a, "add"]);
+ return c
+ }
+ },
+ remove: function (a) {
+ if (a instanceof
+ Array) for (var b = 0; b < a.length; b++) this.remove(a[b]);
+ else if (this.callEvent("onbeforedelete", [a])) {
+ if (!this.exists(a)) return null;
+ b = this.get(a);
+ this.sa && dhtmlxchart.extend(this.get(b.parent).item, dhtmlxchart.PowerArray).remove(a);
+ this.order.remove(a);
+ this.m && this.m.remove(a);
+ delete this.pull[a];
+ this.callEvent("onafterdelete", [a]);
+ this.callEvent("onStoreUpdated", [a, b, "delete"])
+ }
+ },
+ clearAll: function () {
+ this.pull = {};
+ this.order = dhtmlxchart.toArray();
+ this.m = null;
+ this.callEvent("onClearAll", []);
+ this.refresh()
+ },
+ idByIndex: function (a) {
+ return this.order[a]
+ },
+ indexById: function (a) {
+ return a = this.order.find(a)
+ },
+ next: function (a, b) {
+ return this.order[this.indexById(a) + (b || 1)]
+ },
+ first: function () {
+ return this.order[0]
+ },
+ last: function () {
+ return this.order[this.order.length - 1]
+ },
+ previous: function (a, b) {
+ return this.order[this.indexById(a) - (b || 1)]
+ },
+ sort: function (a, b, c) {
+ var d = a;
+ if (typeof a == "function") d = {
+ as: a,
+ dir: b
+ };
+ else if (typeof a == "string") d = {
+ by: a,
+ dir: b,
+ as: c
+ };
+ var e = [d.by, d.dir, d.as];
+ if (this.callEvent("onbeforesort", e)) {
+ if (this.order.length) {
+ var f = dhtmlxchart.sort.create(d),
+ g = this.getRange(this.first(), this.last());
+ g.sort(f);
+ this.order = g.map(function (i) {
+ return this.id(i)
+ }, this)
+ }
+ this.refresh();
+ this.callEvent("onaftersort", e)
+ }
+ },
+ filter: function (a, b) {
+ if (this.m) {
+ this.order = this.m;
+ delete this.m
+ }
+ if (a) {
+ var c = a;
+ if (typeof a == "string") {
+ a = dhtmlxchart.Template.setter(0, a);
+ c = function (e, f) {
+ return a(e).toLowerCase().indexOf(f) != -1
+ }
+ }
+ b = (b || "").toString().toLowerCase();
+ var d = dhtmlxchart.toArray();
+ this.order.each(function (e) {
+ c(this.get(e), b) && d.push(e)
+ }, this);
+ this.m = this.order;
+ this.order = d
+ }
+ this.refresh()
+ },
+ each: function (a, b) {
+ for (var c = 0; c < this.order.length; c++) a.call(b || this, this.get(this.order[c]))
+ },
+ provideApi: function (a, b) {
+ b && this.mapEvent({
+ onbeforesort: a,
+ onaftersort: a,
+ onbeforeadd: a,
+ onafteradd: a,
+ onbeforedelete: a,
+ onafterdelete: a
+ });
+ for (var c = ["sort", "add", "remove", "exists", "idByIndex", "indexById", "get", "set", "refresh", "dataCount", "filter", "next", "previous", "clearAll", "first", "last"], d = 0; d < c.length; d++) a[c[d]] = dhtmlxchart.methodPush(this, c[d])
+ }
+};
+dhtmlxchart.sort = {
+ create: function (a) {
+ return dhtmlxchart.sort.dir(a.dir, dhtmlxchart.sort.by(a.by, a.as))
+ },
+ as: {
+ "int": function (a, b) {
+ a *= 1;
+ b *= 1;
+ return a > b ? 1 : a < b ? -1 : 0
+ },
+ string_strict: function (a, b) {
+ a = a.toString();
+ b = b.toString();
+ return a > b ? 1 : a < b ? -1 : 0
+ },
+ string: function (a, b) {
+ a = a.toString().toLowerCase();
+ b = b.toString().toLowerCase();
+ return a > b ? 1 : a < b ? -1 : 0
+ }
+ },
+ by: function (a, b) {
+ if (typeof b != "function") b = dhtmlxchart.sort.as[b || "string"];
+ a = dhtmlxchart.Template.setter(0, a);
+ return function (c, d) {
+ return b(a(c), a(d))
+ }
+ },
+ dir: function (a, b) {
+ if (a == "asc") return b;
+ return function (c, d) {
+ return b(c, d) * -1
+ }
+ }
+};
+dhtmlxchart.Group = {
+ k: function () {
+ this.data.attachEvent("onStoreLoad", dhtmlxchart.bind(function () {
+ this.e.group && this.group(this.e.group, false)
+ }, this));
+ this.attachEvent("onBeforeRender", dhtmlxchart.bind(function (a) {
+ if (this.e.sort) {
+ a.block();
+ a.sort(this.e.sort);
+ a.unblock()
+ }
+ }, this));
+ this.attachEvent("onBeforeSort", dhtmlxchart.bind(function () {
+ this.e.sort = null
+ }, this))
+ },
+ Ka: function (a, b) {
+ a.attachEvent("onClearAll", dhtmlxchart.bind(function () {
+ this.ungroup(false)
+ }, b))
+ },
+ sum: function (a, b) {
+ a = dhtmlxchart.Template.setter(0, a);
+ b = b || this.data;
+ var c = 0;
+ b.each(function (d) {
+ c += a(d) * 1
+ });
+ return c
+ },
+ min: function (a, b) {
+ a = dhtmlxchart.Template.setter(0, a);
+ b = b || this.data;
+ var c = Infinity;
+ b.each(function (d) {
+ if (a(d) * 1 < c) c = a(d) * 1
+ });
+ return c * 1
+ },
+ max: function (a, b) {
+ a = dhtmlxchart.Template.setter(0, a);
+ b = b || this.data;
+ var c = -Infinity;
+ b.each(function (d) {
+ if (a(d) * 1 > c) c = a(d) * 1
+ });
+ return c
+ },
+ db: function (a) {
+ var b = function (j, k) {
+ j = dhtmlxchart.Template.setter(0, j);
+ return j(k[0])
+ },
+ c = dhtmlxchart.Template.setter(0, a.by);
+ a.map[c] || (a.map[c] = [c, b]);
+ var d = {},
+ e = [];
+ this.data.each(function (j) {
+ var k = c(j);
+ if (!d[k]) {
+ e.push({
+ id: k
+ });
+ d[k] = dhtmlxchart.toArray()
+ }
+ d[k].push(j)
+ });
+ for (var f in a.map) {
+ var g = a.map[f][1] || b;
+ if (typeof g != "function") g = this[g];
+ for (var i = 0; i < e.length; i++) e[i][f] = g.call(this, a.map[f][0], d[e[i].id])
+ }
+ this.ka = this.data;
+ this.data = new dhtmlxchart.DataStore;
+ this.data.provideApi(this, true);
+ this.Ka(this.data, this);
+ this.parse(e, "json")
+ },
+ group: function (a, b) {
+ this.ungroup(false);
+ this.db(a);
+ b !== false && this.render()
+ },
+ ungroup: function (a) {
+ if (this.ka) {
+ this.data = this.ka;
+ this.data.provideApi(this, true)
+ }
+ a !== false && this.render()
+ },
+ group_setter: function (a, b) {
+ return b
+ },
+ sort_setter: function (a, b) {
+ if (typeof b != "object") b = {
+ by: b
+ };
+ this.n(b, {
+ as: "string",
+ dir: "asc"
+ });
+ return b
+ }
+};
+dhtmlxchart.KeyEvents = {
+ k: function () {
+ dhtmlxchart.event(this.g, "keypress", this.Ua, this)
+ },
+ Ua: function (a) {
+ a = a || event;
+ var b = a.which || a.keyCode;
+ this.callEvent(this.hb ? "onEditKeyPress" : "onKeyPress", [b, a.ctrlKey, a.shiftKey, a])
+ }
+};
+dhtmlxchart.MouseEvents = {
+ k: function () {
+ if (this.on_click) {
+ dhtmlxchart.event(this.g, "click", this.Ra, this);
+ dhtmlxchart.event(this.g, "contextmenu", this.Sa, this)
+ }
+ this.on_dblclick && dhtmlxchart.event(this.g, "dblclick", this.Ta, this);
+ if (this.on_mouse_move) {
+ dhtmlxchart.event(this.g, "mousemove", this.ma, this);
+ dhtmlxchart.event(this.g, dhtmlxchart.r ? "mouseleave" : "mouseout", this.ma, this)
+ }
+ },
+ Ra: function (a) {
+ return this.R(a, this.on_click, "ItemClick")
+ },
+ Ta: function (a) {
+ return this.R(a, this.on_dblclick, "ItemDblClick")
+ },
+ Sa: function (a) {
+ var b = dhtmlxchart.html.locate(a, this.q);
+ if (b && !this.callEvent("onBeforeContextMenu", [b, a])) return dhtmlxchart.html.preventEvent(a)
+ },
+ ma: function (a) {
+ if (dhtmlxchart.r) a = document.createEventObject(event);
+ this.ja && window.clearTimeout(this.ja);
+ this.callEvent("onMouseMoving", [a]);
+ this.ja = window.setTimeout(dhtmlxchart.bind(function () {
+ a.type == "mousemove" ? this.Va(a) : this.Wa(a)
+ }, this), 500)
+ },
+ Va: function (a) {
+ this.R(a, this.on_mouse_move, "MouseMove") || this.callEvent("onMouseOut", [a || event])
+ },
+ Wa: function (a) {
+ this.callEvent("onMouseOut", [a || event])
+ },
+ R: function (a, b, c) {
+ a = a || event;
+ for (var d = a.target || a.srcElement, e = "", f = null, g = false; d && d.parentNode;) {
+ if (!g && d.getAttribute) if (f = d.getAttribute(this.q)) {
+ d.getAttribute("userdata") && this.callEvent("onLocateData", [f, d]);
+ if (!this.callEvent("on" + c, [f, a, d])) return;
+ g = true
+ }
+ if (e = d.className) {
+ e = e.split(" ");
+ e = e[0] || e[1];
+ if (b[e]) return b[e].call(this, a, f, d)
+ }
+ d = d.parentNode
+ }
+ return g
+ }
+};
+dhtmlxchart.Settings = {
+ k: function () {
+ this.e = this.config = {}
+ },
+ define: function (a, b) {
+ if (typeof a == "object") return this.na(a);
+ return this.Z(a, b)
+ },
+ Z: function (a, b) {
+ var c = this[a + "_setter"];
+ return this.e[a] = c ? c.call(this, a, b) : b
+ },
+ na: function (a) {
+ if (a) for (var b in a) this.Z(b, a[b])
+ },
+ B: function (a, b) {
+ var c = dhtmlxchart.extend({}, b);
+ typeof a == "object" && !a.tagName && dhtmlxchart.extend(c, a);
+ this.na(c)
+ },
+ n: function (a, b) {
+ for (var c in b) switch (typeof a[c]) {
+ case "object":
+ a[c] = this.n(a[c] || {}, b[c]);
+ break;
+ case "undefined":
+ a[c] = b[c];
+ break;
+ default:
+ break
+ }
+ return a
+ },
+ Ya: function (a, b, c) {
+ if (typeof a == "object" && !a.tagName) a = a.container;
+ this.g = dhtmlxchart.toNode(a);
+ if (!this.g && c) this.g = c(a);
+ this.g.className += " " + b;
+ this.g.onselectstart = function () {
+ return false
+ };
+ this.L = this.g
+ },
+ bb: function (a) {
+ if (typeof a == "object") return this.type_setter("type", a);
+ this.type = dhtmlxchart.extend({}, this.types[a]);
+ this.customize()
+ },
+ customize: function (a) {
+ a && dhtmlxchart.extend(this.type, a);
+ this.type.Pa = dhtmlxchart.Template.fromHTML(this.template_item_start(this.type));
+ this.type.Oa = this.template_item_end(this.type);
+ this.render()
+ },
+ type_setter: function (a, b) {
+ this.bb(typeof b == "object" ? dhtmlxchart.Type.add(this, b) : b);
+ return b
+ },
+ template_setter: function (a, b) {
+ return this.type_setter("type", {
+ template: b
+ })
+ },
+ css_setter: function (a, b) {
+ this.g.className += " " + b;
+ return b
+ }
+};
+dhtmlxchart.compat = function (a, b) {
+ dhtmlxchart.compat[a] && dhtmlxchart.compat[a](b)
+};
+(function () {
+ if (!window.dhtmlxError) {
+ var a = function () {};
+ window.dhtmlxError = {
+ catchError: a,
+ throwError: a
+ };
+ window.convertStringToBoolean = function (c) {
+ return !!c
+ };
+ window.dhtmlxEventable = function (c) {
+ dhtmlxchart.extend(c, dhtmlxchart.EventSystem)
+ };
+ var b = {
+ getXMLTopNode: function () {},
+ doXPath: function (c) {
+ return dhtmlxchart.DataDriver.xml.xpath(this.xml, c)
+ },
+ xmlDoc: {
+ responseXML: true
+ }
+ };
+ dhtmlxchart.compat.dataProcessor = function (c) {
+ var d = "_sendData",
+ e = "_in_progress",
+ f = "_tMode",
+ g = "_waitMode";
+ c[d] = function (i, j) {
+ if (i) {
+ if (j) this[e][j] = (new Date).valueOf();
+ if (!this.callEvent("onBeforeDataSending", j ? [j, this.getState(j)] : [])) return false;
+ var k = this,
+ h = this.serverProcessor;
+ this[f] != "POST" ? dhtmlxchart.ajax().get(h + (h.indexOf("?") != -1 ? "&" : "?") + this.serialize(i, j), "", function (m, l) {
+ b.xml = dhtmlxchart.DataDriver.xml.checkResponse(m, l);
+ k.afterUpdate(k, null, null, null, b)
+ }) : dhtmlxchart.ajax().post(h, this.serialize(i, j), function (m, l) {
+ b.xml = dhtmlxchart.DataDriver.xml.checkResponse(m, l);
+ k.afterUpdate(k, null, null, null, b)
+ });
+ this[g]++
+ }
+ }
+ }
+ }
+})();
+if (!dhtmlxchart.attaches) dhtmlxchart.attaches = {};
+dhtmlxchart.attaches.attachAbstract = function (a, b) {
+ var c = document.createElement("DIV");
+ c.id = "CustomObject_" + dhtmlxchart.uid();
+ c.style.width = "100%";
+ c.style.height = "100%";
+ c.cmp = "grid";
+ document.body.appendChild(c);
+ this.attachObject(c.id);
+ b.container = c.id;
+ var d = this.vs[this.av];
+ d.grid = new window[a](b);
+ d.gridId = c.id;
+ d.gridObj = c;
+ d.grid.setSizes = function () {
+ this.resize ? this.resize() : this.render()
+ };
+ var e = "_viewRestore";
+ return this.vs[this[e]()].grid
+};
+dhtmlxchart.attaches.attachDataView = function (a) {
+ return this.attachAbstract("dhtmlxchartDataView", a)
+};
+dhtmlxchart.attaches.attachChart = function (a) {
+ return this.attachAbstract("dhtmlxchartChart", a)
+};
+dhtmlxchart.compat.layout = function () {};
+dhtmlxchart.ajax = function (a, b, c) {
+ if (arguments.length !== 0) {
+ var d = new dhtmlxchart.ajax;
+ if (c) d.master = c;
+ d.get(a, null, b)
+ }
+ if (!this.getXHR) return new dhtmlxchart.ajax;
+ return this
+};
+dhtmlxchart.ajax.prototype = {
+ getXHR: function () {
+ return dhtmlxchart.r ? new ActiveXObject("Microsoft.xmlHTTP") : new XMLHttpRequest
+ },
+ send: function (a, b, c) {
+ var d = this.getXHR();
+ if (typeof c == "function") c = [c];
+ if (typeof b == "object") {
+ var e = [];
+ for (var f in b) e.push(f + "=" + encodeURIComponent(b[f]));
+ b = e.join("&")
+ }
+ if (b && !this.post) {
+ a = a + (a.indexOf("?") != -1 ? "&" : "?") + b;
+ b = null
+ }
+ d.open(this.post ? "POST" : "GET", a, !this.qa);
+ this.post && d.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+ if (!this.qa) {
+ var g = this;
+ d.onreadystatechange = function () {
+ if (!d.readyState || d.readyState == 4) {
+ if (c && g) for (var i = 0; i < c.length; i++) if (c[i]) c[i].call(g.master || g, d.responseText, d.responseXML, d);
+ c = d = g = g.master = null
+ }
+ }
+ }
+ d.send(b || null);
+ return d
+ },
+ get: function (a, b, c) {
+ this.post = false;
+ return this.send(a, b, c)
+ },
+ post: function (a, b, c) {
+ this.post = true;
+ return this.send(a, b, c)
+ },
+ sync: function () {
+ this.qa = true;
+ return this
+ }
+};
+dhtmlxchart.DataLoader = {
+ k: function () {
+ this.data = new dhtmlxchart.DataStore
+ },
+ load: function (a, b, c) {
+ this.callEvent("onXLS", []);
+ if (typeof b == "string") {
+ this.data.setDriver(b);
+ b = c
+ }
+ if (!this.data.feed) this.data.feed = function (d, e) {
+ if (this.F) return this.F = [d, e];
+ else this.F = true;
+ this.load(a + (a.indexOf("?") == -1 ? "?" : "&") + "posStart=" + d + "&count=" + e, function () {
+ var f = this.F;
+ this.F = false;
+ typeof f == "object" && this.data.feed.apply(this, f)
+ })
+ };
+ dhtmlxchart.ajax(a, [this.la, b], this)
+ },
+ parse: function (a, b) {
+ this.callEvent("onXLS", []);
+ b && this.data.setDriver(b);
+ this.la(a, null)
+ },
+ la: function (a, b) {
+ this.data.Xa(this.data.driver.toObject(a, b));
+ this.callEvent("onXLE", [])
+ }
+};
+dhtmlxchart.DataDriver = {};
+dhtmlxchart.DataDriver.json = {
+ toObject: function (a) {
+ if (typeof a == "string") {
+ eval("dhtmlxchart.temp=" + a);
+ return dhtmlxchart.temp
+ }
+ return a
+ },
+ getRecords: function (a) {
+ if (a && !(a instanceof Array)) return [a];
+ return a
+ },
+ getDetails: function (a) {
+ return a
+ },
+ getInfo: function (a) {
+ return {
+ w: a.total_count || 0,
+ u: a.pos || 0
+ }
+ }
+};
+dhtmlxchart.DataDriver.html = {
+ toObject: function (a) {
+ if (typeof a == "string") {
+ var b = null;
+ if (a.indexOf("<") == -1) b = dhtmlxchart.toNode(a);
+ if (!b) {
+ b = document.createElement("DIV");
+ b.innerHTML = a
+ }
+ return b.getElementsByTagName(this.tag)
+ }
+ return a
+ },
+ getRecords: function (a) {
+ if (a.tagName) return a.childNodes;
+ return a
+ },
+ getDetails: function (a) {
+ return dhtmlxchart.DataDriver.xml.tagToObject(a)
+ },
+ getInfo: function () {
+ return {
+ w: 0,
+ u: 0
+ }
+ },
+ tag: "LI"
+};
+dhtmlxchart.DataDriver.jsarray = {
+ toObject: function (a) {
+ if (typeof a == "string") {
+ eval("dhtmlxchart.temp=" + a);
+ return dhtmlxchart.temp
+ }
+ return a
+ },
+ getRecords: function (a) {
+ return a
+ },
+ getDetails: function (a) {
+ for (var b = {}, c = 0; c < a.length; c++) b["data" + c] = a[c];
+ return b
+ },
+ getInfo: function () {
+ return {
+ w: 0,
+ u: 0
+ }
+ }
+};
+dhtmlxchart.DataDriver.csv = {
+ toObject: function (a) {
+ return a
+ },
+ getRecords: function (a) {
+ return a.split(this.row)
+ },
+ getDetails: function (a) {
+ a = this.stringToArray(a);
+ for (var b = {}, c = 0; c < a.length; c++) b["data" + c] = a[c];
+ return b
+ },
+ getInfo: function () {
+ return {
+ w: 0,
+ u: 0
+ }
+ },
+ stringToArray: function (a) {
+ a = a.split(this.cell);
+ for (var b = 0; b < a.length; b++) a[b] = a[b].replace(/^[ \t\n\r]*(\"|)/g, "").replace(/(\"|)[ \t\n\r]*$/g, "");
+ return a
+ },
+ row: "\n",
+ cell: ","
+};
+dhtmlxchart.DataDriver.xml = {
+ toObject: function (a, b) {
+ if (b && (b = this.checkResponse(a, b))) return b;
+ if (typeof a == "string") return this.fromString(a);
+ return a
+ },
+ getRecords: function (a) {
+ return this.xpath(a, this.records)
+ },
+ records: "/*/item",
+ userdata: "/*/userdata",
+ getDetails: function (a) {
+ return this.tagToObject(a, {})
+ },
+ getUserData: function (a, b) {
+ b = b || {};
+ var c = this.xpath(a, this.userdata);
+ for (a = 0; a < c.length; a++) {
+ var d = this.tagToObject(c[a]);
+ b[d.name] = d.value
+ }
+ return b
+ },
+ getInfo: function (a) {
+ return {
+ w: a.documentElement.getAttribute("total_count") || 0,
+ u: a.documentElement.getAttribute("pos") || 0
+ }
+ },
+ xpath: function (a, b) {
+ if (window.XPathResult) {
+ var c = a;
+ if (a.nodeName.indexOf("document") == -1) a = a.ownerDocument;
+ var d = [];
+ a = a.evaluate(b, c, null, XPathResult.ANY_TYPE, null);
+ for (b = a.iterateNext(); b;) {
+ d.push(b);
+ b = a.iterateNext()
+ }
+ return d
+ }
+ return a.selectNodes(b)
+ },
+ tagToObject: function (a, b) {
+ b = b || {};
+ for (var c = a.attributes, d = 0; d < c.length; d++) b[c[d].name] = c[d].value;
+ var e = false,
+ f = a.childNodes;
+ for (d = 0; d < f.length; d++) if (f[d].nodeType == 1) {
+ var g = f[d].tagName;
+ if (typeof b[g] != "undefined") {
+ b[g] instanceof Array || (b[g] = [b[g]]);
+ b[g].push(this.tagToObject(f[d], {}))
+ } else b[f[d].tagName] = this.tagToObject(f[d], {});
+ e = true
+ }
+ if (!c.length && !e) return this.nodeValue(a);
+ b.value = this.nodeValue(a);
+ return b
+ },
+ nodeValue: function (a) {
+ if (a.firstChild) return a.firstChild.data;
+ return ""
+ },
+ fromString: function (a) {
+ if (window.DOMParser) return (new DOMParser).parseFromString(a, "text/xml");
+ if (window.ActiveXObject) {
+ temp = new ActiveXObject("Microsoft.xmlDOM");
+ temp.loadXML(a);
+ return temp
+ }
+ },
+ checkResponse: function (a, b) {
+ if (b && b.firstChild && b.firstChild.tagName != "parsererror") return b;
+ if (a = this.from_string(a.responseText.replace(/^[\s]+/, ""))) return a
+ }
+};
+dhtmlxchart.DataDriver.dhtmlxgrid = {
+ Ja: "_get_cell_value",
+ toObject: function (a) {
+ return this.fa = a
+ },
+ getRecords: function (a) {
+ return a.rowsBuffer
+ },
+ getDetails: function (a) {
+ for (var b = {}, c = 0; c < this.fa.getColumnsNum(); c++) b["data" + c] = this.fa[this.Ja](a, c);
+ return b
+ },
+ getInfo: function () {
+ return {
+ w: 0,
+ u: 0
+ }
+ }
+};
+dhtmlxchart.Canvas = {
+ k: function () {
+ this.D = []
+ },
+ Za: function (a) {
+ this.l = dhtmlxchart.html.create("canvas", {
+ width: a.offsetWidth,
+ height: a.offsetHeight
+ });
+ a.appendChild(this.l);
+ if (!this.l.getContext) if (dhtmlxchart.r) {
+ dhtmlxchart.require("thirdparty/excanvas/excanvas.js");
+ G_vmlCanvasManager.init_(document);
+ G_vmlCanvasManager.initElement(this.l)
+ }
+ return this.l
+ },
+ getCanvas: function (a) {
+ return (this.l || this.Za(this.g)).getContext(a || "2d")
+ },
+ ab: function () {
+ if (this.l) {
+ this.l.setAttribute("width", this.l.parentNode.offsetWidth);
+ this.l.setAttribute("height", this.l.parentNode.offsetHeight)
+ }
+ },
+ renderText: function (a, b, c, d, e) {
+ if (c) {
+ a = dhtmlxchart.html.create("DIV", {
+ "class": "dhx_canvas_text" + (d ? " " + d : ""),
+ style: "left:" + a + "px; top:" + b + "px;"
+ }, c);
+ this.g.appendChild(a);
+ this.D.push(a);
+ if (e) a.style.width = e + "px";
+ return a
+ }
+ },
+ renderTextAt: function (a, b, c, d, e, f, g) {
+ if (e = this.renderText.call(this, c, d, e, f, g)) {
+ if (a) e.style.top = a == "middle" ? parseInt(d - e.offsetHeight / 2, 10) + "px" : d - e.offsetHeight + "px";
+ if (b) e.style.left = b == "left" ? c - e.offsetWidth + "px" : parseInt(c - e.offsetWidth / 2, 10) + "px"
+ }
+ return e
+ },
+ clearCanvas: function () {
+ for (var a = 0; a < this.D.length; a++) this.g.removeChild(this.D[a]);
+ this.D = [];
+ if (this.g.v) {
+ this.g.v.parentNode.removeChild(this.g.v);
+ this.g.v = null
+ }
+ this.getCanvas().clearRect(0, 0, this.l.offsetWidth, this.l.offsetHeight)
+ }
+};
+dhtmlxchartChart = function (a) {
+ this.name = "Chart";
+ this.version = "3.0";
+ dhtmlxchart.extend(this, dhtmlxchart.Settings);
+ this.Ya(a, "dhx_chart");
+ dhtmlxchart.extend(this, dhtmlxchart.DataLoader);
+ this.data.provideApi(this, true);
+ dhtmlxchart.extend(this, dhtmlxchart.EventSystem);
+ dhtmlxchart.extend(this, dhtmlxchart.MouseEvents);
+ dhtmlxchart.extend(this, dhtmlxchart.Destruction);
+ dhtmlxchart.extend(this, dhtmlxchart.Canvas);
+ dhtmlxchart.extend(this, dhtmlxchart.Group);
+ dhtmlxchart.extend(this, dhtmlxchart.AutoTooltip);
+ for (var b in dhtmlxchart.chart) dhtmlxchart.extend(this, dhtmlxchart.chart[b]);
+ this.B(a, {
+ color: "RAINBOW",
+ alpha: "1",
+ label: false,
+ value: "{obj.value}",
+ padding: {},
+ view: "pie",
+ lineColor: "#ffffff",
+ cant: 0.5,
+ width: 15,
+ labelWidth: 100,
+ line: {},
+ item: {},
+ shadow: true,
+ gradient: false,
+ border: true,
+ labelOffset: 20,
+ origin: "auto"
+ });
+ this.h = [this.e];
+ this.data.attachEvent("onStoreUpdated", dhtmlxchart.bind(function () {
+ this.render()
+ }, this));
+ this.attachEvent("onLocateData", this.eb)
+};
+dhtmlxchartChart.prototype = {
+ q: "dhx_area_id",
+ on_click: {},
+ on_dblclick: {},
+ on_mouse_move: {},
+ resize: function () {
+ this.ab();
+ this.render()
+ },
+ view_setter: function (a, b) {
+ if (typeof this.e.offset == "undefined") this.e.offset = b == "area" || b == "stackedArea" ? false : true;
+ return b
+ },
+ render: function () {
+ if (this.callEvent("onBeforeRender", [this.data])) {
+ this.clearCanvas();
+ this.e.legend && this.Aa(this.getCanvas(), this.data.getRange(), this.g.offsetWidth, this.g.offsetHeight);
+ for (var a = this.Fa(this.g.offsetWidth, this.g.offsetHeight), b = new dhtmlxchart.ui.Map(this.q), c = this.e, d = 0; d < this.h.length; d++) {
+ this.e = this.h[d];
+ this["pvt_render_" + this.e.view](this.getCanvas(), this.data.getRange(), a.start, a.end, d, b)
+ }
+ b.render(this.g);
+ this.e = c
+ }
+ },
+ value_setter: dhtmlxchart.Template.obj_setter,
+ alpha_setter: dhtmlxchart.Template.obj_setter,
+ label_setter: dhtmlxchart.Template.obj_setter,
+ lineColor_setter: dhtmlxchart.Template.obj_setter,
+ pieInnerText_setter: dhtmlxchart.Template.obj_setter,
+ gradient_setter: function (a, b) {
+ if (typeof b != "function" && b && (b === true || b != "3d")) b = "light";
+ return b
+ },
+ colormap: {
+ RAINBOW: function (a) {
+ a = Math.floor(this.indexById(a.id) / this.dataCount() * 1536);
+ if (a == 1536) a -= 1;
+ return this.$a[Math.floor(a / 256)](a % 256)
+ }
+ },
+ color_setter: function (a, b) {
+ return this.colormap[b] || dhtmlxchart.Template.obj_setter(a, b)
+ },
+ legend_setter: function (a, b) {
+ if (typeof b != "object") b = {
+ template: b
+ };
+ this.n(b, {
+ width: 150,
+ height: 18,
+ layout: "y",
+ align: "left",
+ valign: "bottom",
+ template: "",
+ marker: {
+ type: "square",
+ width: 25,
+ height: 15
+ }
+ });
+ b.template = dhtmlxchart.Template.setter(0, b.template);
+ return b
+ },
+ item_setter: function (a, b) {
+ if (typeof b != "object") b = {
+ color: b,
+ borderColor: b
+ };
+ this.n(b, {
+ radius: 4,
+ color: "#000000",
+ borderColor: "#000000",
+ borderWidth: 2
+ });
+ b.color = dhtmlxchart.Template.setter(0, b.color);
+ b.borderColor = dhtmlxchart.Template.setter(0, b.borderColor);
+ return b
+ },
+ line_setter: function (a, b) {
+ if (typeof b != "object") b = {
+ color: b
+ };
+ this.n(b, {
+ width: 3,
+ color: "#d4d4d4"
+ });
+ b.color = dhtmlxchart.Template.setter(0, b.color);
+ return b
+ },
+ padding_setter: function (a, b) {
+ if (typeof b != "object") b = {
+ left: b,
+ right: b,
+ top: b,
+ bottom: b
+ };
+ this.n(b, {
+ left: 50,
+ right: 20,
+ top: 35,
+ bottom: 40
+ });
+ return b
+ },
+ xAxis_setter: function (a, b) {
+ if (!b) return false;
+ if (typeof b != "object") b = {
+ template: b
+ };
+ this.n(b, {
+ title: "",
+ color: "#000000",
+ template: "{obj}",
+ lines: false
+ });
+ if (b.template) b.template = dhtmlxchart.Template.setter(0, b.template);
+ return b
+ },
+ yAxis_setter: function (a, b) {
+ this.n(b, {
+ title: "",
+ color: "#000000",
+ template: "{obj}",
+ lines: true
+ });
+ if (b.template) b.template = dhtmlxchart.Template.setter(0, b.template);
+ return b
+ },
+ N: function (a, b, c, d, e, f, g) {
+ e = this.Ea(a, b, c, d, e, f);
+ this.ea(a, b, c, d, g, e);
+ return e
+ },
+ ea: function (a, b, c, d, e, f) {
+ if (this.e.xAxis) {
+ var g = c.x - 0.5;
+ f = parseInt(f ? f : d.y, 10) + 0.5;
+ var i = d.x,
+ j, k = true;
+ this.i(a, g, f, i, f, this.e.xAxis.color, 1);
+ for (var h = 0; h < b.length; h++) {
+ if (this.e.offset === true) j = g + e / 2 + h * e;
+ else {
+ j = g + h * e;
+ k = !! h
+ }
+ var m = this.e.origin != "auto" && this.e.view == "bar" && parseFloat(this.e.value(b[h])) < this.e.origin;
+ this.Ca(j, f, b[h], k, m);
+ this.e.view_setter != "bar" && this.Da(a, j, d.y, c.y)
+ }
+ this.renderTextAt(true, false, g, d.y + this.e.padding.bottom - 3, this.e.xAxis.title, "dhx_axis_title_x", d.x - c.x);
+ this.e.xAxis.lines && this.e.offset && this.i(a, i + 0.5, d.y, i + 0.5, c.y + 0.5, this.e.xAxis.color, 0.2)
+ }
+ },
+ Ea: function (a, b, c, d, e, f) {
+ var g;
+ b = {};
+ if (this.e.yAxis) {
+ var i = c.x - 0.5,
+ j = d.y,
+ k = c.y,
+ h = d.y;
+ this.i(a, i, j, i, k, this.e.yAxis.color, 1);
+ if (this.e.yAxis.step) g = parseFloat(this.e.yAxis.step);
+ if (typeof this.e.yAxis.step == "undefined" || typeof this.e.yAxis.start == "undefined" || typeof this.e.yAxis.end == "undefined") {
+ b = this.W(e, f);
+ e = b.start;
+ f = b.end;
+ g = b.step;
+ this.e.yAxis.end = f;
+ this.e.yAxis.start = e
+ }
+ if (g !== 0) {
+ k = (j - k) * g / (f - e);
+ for (var m = 0, l = e; l <= f; l += g) {
+ if (b.fixNum) l = parseFloat((new Number(l)).toFixed(b.fixNum));
+ var n = Math.floor(j - m * k) + 0.5;
+ !(l == e && this.e.origin == "auto") && this.e.yAxis.lines && this.i(a, i, n, d.x, n, this.e.yAxis.color, 0.2);
+ if (l == this.e.origin) h = n;
+ this.renderText(0, n - 5, this.e.yAxis.template(l.toString()), "dhx_axis_item_y", c.x - 5);
+ m++
+ }
+ this.pa(c, d);
+ return h
+ }
+ }
+ },
+ pa: function (a, b) {
+ if (a = this.renderTextAt("middle", false, 0, parseInt((b.y - a.y) / 2 + a.y, 10), this.e.yAxis.title, "dhx_axis_title_y")) a.style.left = (dhtmlxchart.env.transform ? (a.offsetHeight - a.offsetWidth) / 2 : 0) + "px"
+ },
+ W: function (a, b) {
+ if (this.e.origin != "auto" && this.e.origin < a) a = this.e.origin;
+ var c, d, e;
+ c = (b - a) / 8 || 1;
+ var f = Math.floor(this.ha(c)),
+ g = Math.pow(10, f),
+ i = c / g;
+ i = i > 5 ? 10 : 5;
+ c = parseInt(i, 10) * g;
+ if (c > Math.abs(a)) d = a < 0 ? -c : 0;
+ else {
+ var j = Math.abs(a),
+ k = Math.floor(this.ha(j)),
+ h = j / Math.pow(10, k);
+ d = Math.ceil(h * 10) / 10 * Math.pow(10, k) - c;
+ if (a < 0) d = -d - 2 * c
+ }
+ for (e = d; e < b;) {
+ e += c;
+ e = parseFloat((new Number(e)).toFixed(Math.abs(f)))
+ }
+ return {
+ start: d,
+ end: e,
+ step: c,
+ fixNum: Math.abs(f)
+ }
+ },
+ O: function (a) {
+ var b, c;
+ if ((c = arguments.length && a == "h" ? this.e.xAxis : this.e.yAxis) && typeof c.end != "undefied" && typeof c.start != "undefied" && c.step) {
+ b = parseFloat(c.end);
+ c = parseFloat(c.start)
+ } else {
+ b = this.max(this.h[0].value);
+ c = this.min(this.h[0].value);
+ if (this.h.length > 1) for (var d = 1; d < this.h.length; d++) {
+ var e = this.max(this.h[d].value),
+ f = this.min(this.h[d].value);
+ if (e > b) b = e;
+ if (f < c) c = f
+ }
+ }
+ return {
+ max: b,
+ min: c
+ }
+ },
+ ha: function (a) {
+ var b = "log";
+ return Math.floor(Math[b](a) / Math.LN10)
+ },
+ Ca: function (a, b, c, d, e) {
+ this.e.xAxis && this.renderTextAt(e, d, a, b, this.e.xAxis.template(c), "dhx_axis_item_x")
+ },
+ Da: function (a, b, c, d) {
+ this.e.xAxis && this.e.xAxis.lines && this.i(a, b, c, b, d, this.e.xAxis.color, 0.2)
+ },
+ i: function (a, b, c, d, e, f, g) {
+ a.strokeStyle = f;
+ a.lineWidth = g;
+ a.beginPath();
+ a.moveTo(b, c);
+ a.lineTo(d, e);
+ a.stroke()
+ },
+ z: function (a, b) {
+ var c = 1;
+ if (b != a) {
+ a = b - a;
+ if (Math.abs(a) < 1) for (; Math.abs(a) < 1;) {
+ c *= 10;
+ a *= c
+ }
+ } else a = a;
+ return [a, c]
+ },
+ $a: [function (a) {
+ return "#FF" + dhtmlxchart.math.toHex(a / 2, 2) + "00"
+ }, function (a) {
+ return "#FF" + dhtmlxchart.math.toHex(a / 2 + 128, 2) + "00"
+ }, function (a) {
+ return "#" + dhtmlxchart.math.toHex(255 - a, 2) + "FF00"
+ }, function (a) {
+ return "#00FF" + dhtmlxchart.math.toHex(a, 2)
+ }, function (a) {
+ return "#00" + dhtmlxchart.math.toHex(255 - a, 2) + "FF"
+ }, function (a) {
+ return "#" + dhtmlxchart.math.toHex(a, 2) + "00FF"
+ }],
+ addSeries: function (a) {
+ var b = this.e;
+ this.e = dhtmlxchart.extend({}, b);
+ this.B(a, {});
+ this.h.push(this.e);
+ this.e = b
+ },
+ eb: function (a, b) {
+ this.U = b.getAttribute("userdata");
+ if (this.h[this.U]) {
+ for (a = 0; a < this.h.length; a++) {
+ var c = this.h[a].tooltip;
+ c && c.disable()
+ }(c = this.h[this.U].tooltip) && c.enable()
+ }
+ },
+ Aa: function (a, b) {
+ var c = 0,
+ d = 0,
+ e = this.e.legend,
+ f, g, i = this.e.legend.layout != "x" ? "width:" + e.width + "px" : "";
+ if (this.legendObj) this.legendObj.innerHTML = "";
+ var j = dhtmlxchart.html.create("DIV", {
+ "class": "dhx_chart_legend",
+ style: "position:absolute;left:" + c + "px; top:" + d + "px;" + i
+ }, "");
+ this.legendObj = j;
+ this.g.appendChild(j);
+ var k = [];
+ if (e.values) for (h = 0; h < e.values.length; h++) k.push(this.ba(j, e.values[h].text));
+ else for (var h = 0; h < b.length; h++) k.push(this.ba(j, e.template(b[h])));
+ g = j.offsetWidth;
+ f = j.offsetHeight;
+ this.e.legend.width = g;
+ this.e.legend.height = f;
+ if (g < this.g.offsetWidth) {
+ if (e.layout == "x" && e.align == "center") c = (this.g.offsetWidth - g) / 2;
+ if (e.align == "right") c = this.g.offsetWidth - g
+ }
+ if (f < this.g.offsetHeight) if (e.valign == "middle" && e.align != "center" && e.layout != "x") d = (this.g.offsetHeight - f) / 2;
+ else if (e.valign == "bottom") d = this.g.offsetHeight - f;
+ j.style.left = c + "px";
+ j.style.top = d + "px";
+ for (h = 0; h < k.length; h++) {
+ var m = k[h],
+ l = e.values ? e.values[h].color : this.e.color.call(this, b[h]);
+ this.Ba(a, m.offsetLeft + c, m.offsetTop + d, l)
+ }
+ k = null
+ },
+ ba: function (a, b) {
+ var c = "";
+ if (this.e.legend.layout == "x") c = "float:left;";
+ b = dhtmlxchart.html.create("DIV", {
+ style: c + "padding-left:" + (10 + this.e.legend.marker.width) + "px",
+ "class": "dhx_chart_legend_item"
+ }, b);
+ a.appendChild(b);
+ return b
+ },
+ Ba: function (a, b, c, d) {
+ var e = this.e.legend;
+ a.strokeStyle = a.fillStyle = d;
+ a.lineWidth = e.marker.height;
+ a.lineCap = e.marker.type;
+ a.beginPath();
+ b += a.lineWidth / 2 + 5;
+ c += a.lineWidth / 2 + 3;
+ a.moveTo(b, c);
+ b = b + e.marker.width - e.marker.height + 1;
+ a.lineTo(b, c);
+ a.stroke()
+ },
+ Fa: function (a, b) {
+ var c, d, e, f;
+ c = this.e.padding.left;
+ d = this.e.padding.top;
+ e = a - this.e.padding.right;
+ f = b - this.e.padding.bottom;
+ if (this.e.legend) {
+ a = this.e.legend;
+ b = this.e.legend.width;
+ var g = this.e.legend.height;
+ if (a.layout == "x") if (a.valign == "center") if (a.align == "right") e -= b;
+ else {
+ if (a.align == "left") c += b
+ } else if (a.valign == "bottom") f -= g;
+ else d += g;
+ else if (a.align == "right") e -= b;
+ else if (a.align == "left") c += b
+ }
+ return {
+ start: {
+ x: c,
+ y: d
+ },
+ end: {
+ x: e,
+ y: f
+ }
+ }
+ },
+ Q: function (a) {
+ var b, c;
+ if (this.e.yAxis && typeof this.e.yAxis.end != "undefied" && typeof this.e.yAxis.start != "undefied" && this.e.yAxis.step) {
+ b = parseFloat(this.e.yAxis.end);
+ c = parseFloat(this.e.yAxis.start)
+ } else {
+ for (var d = 0; d < a.length; d++) {
+ a[d].$sum = 0;
+ a[d].$min = Infinity;
+ for (b = 0; b < this.h.length; b++) {
+ c = parseFloat(this.h[b].value(a[d]));
+ if (!isNaN(c)) {
+ a[d].$sum += c;
+ if (c < a[d].$min) a[d].$min = c
+ }
+ }
+ }
+ b = -Infinity;
+ c = Infinity;
+ for (d = 0; d < a.length; d++) {
+ if (a[d].$sum > b) b = a[d].$sum;
+ if (a[d].$min < c) c = a[d].$min
+ }
+ if (c > 0) c = 0
+ }
+ return {
+ max: b,
+ min: c
+ }
+ },
+ G: function (a, b, c, d, e, f, g, i) {
+ if (f == "light") {
+ a = i == "x" ? a.createLinearGradient(b, c, d, c) : a.createLinearGradient(b, c, b, e);
+ a.addColorStop(0, "#FFFFFF");
+ a.addColorStop(0.9, g);
+ a.addColorStop(1, g);
+ g = 2
+ } else {
+ a.globalAlpha = 0.37;
+ g = 0;
+ a = i == "x" ? a.createLinearGradient(b, e, b, c) : a.createLinearGradient(b, c, d, c);
+ a.addColorStop(0, "#000000");
+ a.addColorStop(0.5, "#FFFFFF");
+ a.addColorStop(0.6, "#FFFFFF");
+ a.addColorStop(1, "#000000")
+ }
+ return {
+ gradient: a,
+ offset: g
+ }
+ }
+};
+dhtmlxchart.compat("layout"); \ No newline at end of file
diff --git a/addons/base_graph/static/lib/dhtmlxGraph/codebase/dhtmlxchart_debug.css b/addons/base_graph/static/lib/dhtmlxGraph/codebase/dhtmlxchart_debug.css
new file mode 100644
index 00000000000..c30fbda2da3
--- /dev/null
+++ b/addons/base_graph/static/lib/dhtmlxGraph/codebase/dhtmlxchart_debug.css
@@ -0,0 +1,6 @@
+/*
+Copyright DHTMLX LTD. http://www.dhtmlx.com
+You allowed to use this component or parts of it under GPL terms
+To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlx.com
+*/
+/*pure colors*/ /*fonts*/ /*2010 September 28*//* DHX DEPEND FROM FILE 'tooltip.css'*//*style used by tooltip's container*/ .dhx_tooltip{ display:none; position:absolute; font-family:Tahoma; font-size:8pt; z-index:10000; background-color:white; padding:2px 2px 2px 2px; border:1px solid #A4BED4; }/* DHX DEPEND FROM FILE 'chart.css'*//*chart container*/ .dhx_chart{ position:relative; font-family:Verdana; font-size:13px; color:#000000; overflow:hidden; } /*labels*/ .dhx_canvas_text{ position:absolute; text-align:center; overflow:hidden; white-space:nowrap; } /*map*/ .dhx_map_img{ width : 100%; height : 100%; position : absolute; top : 0px; left : 0px; border:0px; filter:alpha(opacity=0); } /*scales*/ .dhx_axis_item_y{ position:absolute; height:10px; line-height:10px; text-align:right; } .dhx_axis_title_x{ text-align:center; } .dhx_axis_title_y{ text-align:center; font-family:Verdana; /*safari*/ -webkit-transform: rotate(-90deg); /*firefox*/ -moz-transform: rotate(-90deg); /*IE*/ filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); /*opera*/ -o-transform:rotate(-90deg); padding-left:3px; } /*legend block*/ .dhx_chart_legend{ position:absolute; } .dhx_chart_legend_item{ height:18px; line-height:18px; padding: 2px; } \ No newline at end of file
diff --git a/addons/base_graph/static/lib/dhtmlxGraph/codebase/dhtmlxchart_debug.js b/addons/base_graph/static/lib/dhtmlxGraph/codebase/dhtmlxchart_debug.js
new file mode 100644
index 00000000000..57e5b5d5b0d
--- /dev/null
+++ b/addons/base_graph/static/lib/dhtmlxGraph/codebase/dhtmlxchart_debug.js
@@ -0,0 +1,4737 @@
+/*
+Copyright DHTMLX LTD. http://www.dhtmlx.com
+You allowed to use this component or parts of it under GPL terms
+To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlx.com
+*/
+/*
+2010 September 30
+*/
+
+
+
+/* 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<rules.length; i++)
+ if (!rules[i][3] && !rules[i][2](arguments[i]))
+ dhtmlx.log("warn","Incorrect method call\n"+obj[name].describe()+"\n\nActual value of "+(i+1)+" parameter: {"+(typeof arguments[i])+"} "+arguments[i]);
+
+ return old.apply(this, arguments);
+ };
+ obj[name].describe = function(){ return dhtmlx.assert_method_info(obj, name, descr, rules); };
+};
+dhtmlx.assert_event_call = function(obj, name, args){
+ if (obj._event_check){
+ if (!obj._event_check[name])
+ dhtmlx.log("warn","Not expected event call :"+name);
+ else if (dhtmlx.isNotDefined(args))
+ dhtmlx.log("warn","Event without parameters :"+name);
+ else if (obj._event_check_size[name] != args.length)
+ dhtmlx.log("warn","Incorrect event call, expected "+obj._event_check_size[name]+" parameter(s), but have "+args.length +" parameter(s), for "+name+" event");
+ }
+};
+dhtmlx.assert_event_attach = function(obj, name){
+ if (obj._event_check && !obj._event_check[name])
+ dhtmlx.log("warn","Unknown event name: "+name);
+};
+//register names of properties, which can be used in object's configuration
+dhtmlx.assert_property = function(obj, evs){
+ if (!obj._settings_check)
+ obj._settings_check={};
+ dhtmlx.extend(obj._settings_check, evs);
+};
+//check all options in collection, against list of allowed properties
+dhtmlx.assert_check = function(data,coll){
+ if (typeof data == "object"){
+ for (var key in data){
+ dhtmlx.assert_settings(key,data[key],coll);
+ }
+ }
+};
+//check if type and value of property is the same as in scheme
+dhtmlx.assert_settings = function(mode,value,coll){
+ coll = coll || this._settings_check;
+
+ //if value is not in collection of defined ones
+ if (coll){
+ if (!coll[mode]) //not registered property
+ return dhtmlx.log("warn","Unknown propery: "+mode);
+
+ var descr = "";
+ var error = "";
+ var check = false;
+ for (var i=0; i<coll[mode].length; i++){
+ var rule = coll[mode][i];
+ if (typeof rule == "string")
+ continue;
+ if (typeof rule == "function")
+ check = check || rule(value);
+ else if (typeof rule == "object" && typeof rule[1] == "function"){
+ check = check || rule[1](value);
+ if (check && rule[2])
+ dhtmlx["assert_check"](value, rule[2]); //temporary fix , for sources generator
+ }
+ if (check) break;
+ }
+ if (!check )
+ dhtmlx.log("warn","Invalid configuration\n"+dhtmlx.assert_info(mode,coll)+"\nActual value: {"+(typeof value)+"} "+value);
+ }
+};
+
+dhtmlx.assert_info=function(name, set){
+ var ruleset = set[name];
+ var descr = "";
+ var expected = [];
+ for (var i=0; i<ruleset.length; i++){
+ if (typeof rule == "string")
+ descr = ruleset[i];
+ else if (ruleset[i].describe)
+ expected.push(ruleset[i].describe());
+ else if (ruleset[i][1] && ruleset[i][1].describe)
+ expected.push(ruleset[i][1].describe());
+ }
+ return "Property: "+name+", "+descr+" \nExpected value: \n - "+expected.join("\n - ");
+};
+
+
+if (dhtmlx.assert_enabled()){
+
+ dhtmlx.assert_rule_color=function(check){
+ if (typeof check != "string") return false;
+ if (check.indexOf("#")!==0) return false;
+ if (check.substr(1).replace(/[0-9A-F]/gi,"")!=="") return false;
+ return true;
+ };
+ dhtmlx.assert_rule_color.describe = function(){
+ return "{String} Value must start from # and contain hexadecimal code of color";
+ };
+
+ dhtmlx.assert_rule_template=function(check){
+ if (typeof check == "function") return true;
+ if (typeof check == "string") return true;
+ return false;
+ };
+ dhtmlx.assert_rule_template.describe = function(){
+ return "{Function},{String} Value must be a function which accepts data object and return text string, or a sting with optional template markers";
+ };
+
+ dhtmlx.assert_rule_boolean=function(check){
+ if (typeof check == "boolean") return true;
+ return false;
+ };
+ dhtmlx.assert_rule_boolean.describe = function(){
+ return "{Boolean} true or false";
+ };
+
+ dhtmlx.assert_rule_object=function(check, sub){
+ if (typeof check == "object") return true;
+ return false;
+ };
+ dhtmlx.assert_rule_object.describe = function(){
+ return "{Object} Configuration object";
+ };
+
+
+ dhtmlx.assert_rule_string=function(check){
+ if (typeof check == "string") return true;
+ return false;
+ };
+ dhtmlx.assert_rule_string.describe = function(){
+ return "{String} Plain string";
+ };
+
+
+ dhtmlx.assert_rule_htmlpt=function(check){
+ return !!dhtmlx.toNode(check);
+ };
+ dhtmlx.assert_rule_htmlpt.describe = function(){
+ return "{Object},{String} HTML node or ID of HTML Node";
+ };
+
+ dhtmlx.assert_rule_notdocumented=function(check){
+ return false;
+ };
+ dhtmlx.assert_rule_notdocumented.describe = function(){
+ return "This options wasn't documented";
+ };
+
+ dhtmlx.assert_rule_key=function(obj){
+ var t = function (check){
+ return obj[check];
+ };
+ t.describe=function(){
+ var opts = [];
+ for(var key in obj)
+ opts.push(key);
+ return "{String} can take one of next values: "+opts.join(", ");
+ };
+ return t;
+ };
+
+ dhtmlx.assert_rule_dimension=function(check){
+ if (check*1 == check && !isNaN(check) && check >= 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;
+ }
+
+ dhtmlx.assert(target,"Invalid nesting target");
+ dhtmlx.assert(source,"Invalid nesting source");
+ //if source object has init code - call init against target
+ if (source._init)
+ target._init();
+
+ return target;
+};
+dhtmlx.proto_extend = function(){
+ var origins = arguments;
+ var compilation = origins[0];
+ var construct = [];
+
+ for (var i=origins.length-1; i>0; i--) {
+ if (typeof origins[i]== "function")
+ origins[i]=origins[i].prototype;
+ for (var key in origins[i]){
+ if (key == "_init")
+ construct.push(origins[i][key]);
+ else if (!compilation[key])
+ compilation[key] = origins[i][key];
+ }
+ };
+
+ if (origins[0]._init)
+ construct.push(origins[0]._init);
+
+ compilation._init = function(){
+ for (var i=0; i<construct.length; i++)
+ construct[i].apply(this, arguments);
+ };
+ compilation.base = origins[1];
+ var result = function(config){
+ this._init(config);
+ if (this._parseSettings)
+ this._parseSettings(config, this.defaults);
+ };
+ result.prototype = compilation;
+
+ compilation = origins = null;
+ return result;
+};
+//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, delay){
+ setTimeout(function(){
+ var ret = method.apply(obj,params);
+ method = obj = params = null;
+ return ret;
+ },delay||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||"unknown error");
+ 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<event_stack.length; i++)
+ /*
+ Call events one by one
+ If any event return false - result of whole event will be false
+ Handlers which are not returning anything - counted as positive
+ */
+ if (event_stack[i].apply(this,(params||[]))===false) return_value=false;
+
+ if (this._map[type] && !this._map[type].callEvent(type,params))
+ return_value = false;
+
+ return return_value;
+ },
+ //assign handler for some named event
+ attachEvent:function(type,functor,id){
+ type=type.toLowerCase();
+ dhtmlx.assert_event_attach(this, type);
+
+ id=id||dhtmlx.uid(); //ID can be used for detachEvent
+ functor = dhtmlx.toFunctor(functor); //functor can be a name of method
+
+ var event_stack=this._events[type]||dhtmlx.toArray();
+ //save new event handler
+ event_stack.push(functor);
+ this._events[type]=event_stack;
+ this._handlers[id]={ f:functor,t:type };
+
+ return id;
+ },
+ //remove event handler
+ detachEvent:function(id){
+ var type=this._handlers[id].t;
+ var functor=this._handlers[id].f;
+
+ //remove from all collections
+ var event_stack=this._events[type];
+ event_stack.remove(functor);
+ delete this._handlers[id];
+ }
+};
+
+//array helper
+//can be used by dhtmlx.toArray()
+dhtmlx.PowerArray={
+ //remove element at specified position
+ removeAt:function(pos,len){
+ if (pos>=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; i<this.length; i++)
+ if (data==this[i]) return i;
+ return -1;
+ },
+ //execute some method for each element of array
+ each:function(functor,master){
+ for (var i=0; i < this.length; i++)
+ functor.call((master||this),this[i]);
+ },
+ //create new array from source, by using results of functor
+ map:function(functor,master){
+ for (var i=0; i < this.length; i++)
+ this[i]=functor.call((master||this),this[i]);
+ return this;
+ }
+};
+
+dhtmlx.env = {};
+
+//environment detection
+if (navigator.userAgent.indexOf('Opera') != -1)
+ dhtmlx._isOpera=true;
+else{
+ //very rough detection, but it is enough for current goals
+ dhtmlx._isIE=!!document.all;
+ dhtmlx._isFF=!document.all;
+ dhtmlx._isWebKit=(navigator.userAgent.indexOf("KHTML")!=-1);
+ if (navigator.appVersion.indexOf("MSIE 8.0")!= -1 && document.compatMode != "BackCompat")
+ dhtmlx._isIE=8;
+}
+
+dhtmlx.env = {};
+
+// dhtmlx.env.transform
+// dhtmlx.env.transition
+(function(){
+ dhtmlx.env.transform = false;
+ dhtmlx.env.transition = false;
+ var options = {};
+ options.names = ['transform', 'transition'];
+ options.transform = ['transform', 'WebkitTransform', 'MozTransform', 'oTransform'];
+ options.transition = ['transition', 'WebkitTransition', 'MozTransition', 'oTransition'];
+
+ var d = document.createElement("DIV");
+ var property;
+ for(var i=0; i<options.names.length; i++) {
+ while (p = options[options.names[i]].pop()) {
+ if(typeof d.style[p] != 'undefined')
+ dhtmlx.env[options.names[i]] = true;
+ }
+ }
+})();
+dhtmlx.env.transform_prefix = (function(){
+ var prefix;
+ if(dhtmlx._isOpera)
+ prefix = '-o-';
+ else {
+ prefix = ''; // default option
+ if(dhtmlx._isFF)
+ prefix = '-moz-';
+ if(dhtmlx._isWebKit)
+ prefix = '-webkit-';
+ }
+ return prefix;
+})();
+dhtmlx.env.svg = (function(){
+ return document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1");
+})();
+
+//store maximum used z-index
+dhtmlx.zIndex={ drag : 10000 };
+
+//html helpers
+dhtmlx.html={
+ create:function(name,attrs,html){
+ attrs = attrs || {};
+ var node = document.createElement(name);
+ for (var attr_name in attrs)
+ node.setAttribute(attr_name, attrs[attr_name]);
+ if (attrs.style)
+ node.style.cssText = attrs.style;
+ if (attrs["class"])
+ node.className = attrs["class"];
+ if (html)
+ node.innerHTML=html;
+ return node;
+ },
+ //return node value, different logic for different html elements
+ getValue:function(node){
+ node = dhtmlx.toNode(node);
+ if (!node) return "";
+ return dhtmlx.isNotDefined(node.value)?node.innerHTML:node.value;
+ },
+ //remove html node, can process an array of nodes at once
+ remove:function(node){
+ if (node instanceof Array)
+ for (var i=0; i < node.length; i++)
+ this.remove(node[i]);
+ else
+ if (node && node.parentNode)
+ node.parentNode.removeChild(node);
+ },
+ //insert new node before sibling, or at the end if sibling doesn't exist
+ insertBefore: function(node,before,rescue){
+ if (!node) return;
+ if (before)
+ before.parentNode.insertBefore(node, before);
+ else
+ rescue.appendChild(node);
+ },
+ //return custom ID from html element
+ //will check all parents starting from event's target
+ locate:function(e,id){
+ e=e||event;
+ var trg=e.target||e.srcElement;
+ while (trg){
+ if (trg.getAttribute){ //text nodes has not getAttribute
+ var test = trg.getAttribute(id);
+ if (test) return test;
+ }
+ trg=trg.parentNode;
+ }
+ return null;
+ },
+ //returns position of html element on the page
+ offset:function(elem) {
+ if (elem.getBoundingClientRect) { //HTML5 method
+ var box = elem.getBoundingClientRect();
+ var body = document.body;
+ var docElem = document.documentElement;
+ var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;
+ var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;
+ var clientTop = docElem.clientTop || body.clientTop || 0;
+ var clientLeft = docElem.clientLeft || body.clientLeft || 0;
+ var top = box.top + scrollTop - clientTop;
+ var left = box.left + scrollLeft - clientLeft;
+ return { y: Math.round(top), x: Math.round(left) };
+ } else { //fallback to naive approach
+ var top=0, left=0;
+ while(elem) {
+ top = top + parseInt(elem.offsetTop,10);
+ left = left + parseInt(elem.offsetLeft,10);
+ elem = elem.offsetParent;
+ }
+ return {y: top, x: left};
+ }
+ },
+ //returns position of event
+ pos:function(ev){
+ ev = ev || event;
+ if(ev.pageX || ev.pageY) //FF, KHTML
+ return {x:ev.pageX, y:ev.pageY};
+ //IE
+ var d = ((dhtmlx._isIE)&&(document.compatMode != "BackCompat"))?document.documentElement:document.body;
+ return {
+ x:ev.clientX + d.scrollLeft - d.clientLeft,
+ y:ev.clientY + d.scrollTop - d.clientTop
+ };
+ },
+ //prevent event action
+ preventEvent:function(e){
+ if (e && e.preventDefault) e.preventDefault();
+ dhtmlx.html.stopEvent(e);
+ },
+ //stop event bubbling
+ stopEvent:function(e){
+ (e||event).cancelBubble=true;
+ return false;
+ },
+ //add css class to the node
+ addCss:function(node,name){
+ node.className+=" "+name;
+ },
+ //remove css class from the node
+ removeCss:function(node,name){
+ node.className=node.className.replace(RegExp(name,"g"),"");
+ }
+};
+
+//autodetect codebase folder
+(function(){
+ var temp = document.getElementsByTagName("SCRIPT"); //current script, most probably
+ dhtmlx.assert(temp.length,"Can't locate codebase");
+ if (temp.length){
+ //full path to script
+ temp = (temp[temp.length-1].getAttribute("src")||"").split("/");
+ //get folder name
+ temp.splice(temp.length-1, 1);
+ dhtmlx.codebase = temp.slice(0, temp.length).join("/")+"/";
+ }
+})();
+
+dhtmlx.ui={};
+
+
+/* DHX DEPEND FROM FILE 'destructor.js'*/
+
+
+/*
+ Behavior:Destruction
+
+ @export
+ destructor
+*/
+
+/*DHX:Depend dhtmlx.js*/
+
+dhtmlx.Destruction = {
+ _init:function(){
+ //register self in global list of destructors
+ dhtmlx.destructors.push(this);
+ },
+ //will be called automatically on unload, can be called manually
+ //simplifies job of GC
+ destructor:function(){
+ this.destructor=function(){}; //destructor can be called only once
+
+ //html collection
+ this._htmlmap = null;
+ this._htmlrows = null;
+
+ //temp html element, used by toHTML
+ if (this._html)
+ document.body.appendChild(this._html); //need to attach, for IE's GC
+
+ this._html = null;
+ if (this._obj) {
+ this._obj.innerHTML="";
+ this._obj._htmlmap = null;
+ }
+ this._obj = this._dataobj=null;
+ this.data = null;
+ this._events = this._handlers = {};
+ }
+};
+//global list of destructors
+dhtmlx.destructors = [];
+dhtmlx.event(window,"unload",function(){
+ //call all registered destructors
+ for (var i=0; i<dhtmlx.destructors.length; i++)
+ dhtmlx.destructors[i].destructor();
+ dhtmlx.destructors = [];
+
+ //detach all known DOM events
+ for (var a in dhtmlx._events){
+ var ev = dhtmlx._events[a];
+ 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 dhtmlx._events[a];
+ }
+});
+
+
+/* DHX DEPEND FROM FILE 'math.js'*/
+
+
+dhtmlx.math = {};
+dhtmlx.math._toHex=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"];
+dhtmlx.math.toHex = function(number, length){
+ number=parseInt(number,10);
+ str = "";
+ while (number>0){
+ str=this._toHex[number%16]+str;
+ number=Math.floor(number/16);
+ }
+ while (str.length <length)
+ str = "0"+str;
+ return str;
+};
+
+
+
+
+
+/* DHX DEPEND FROM FILE 'map.js'*/
+
+
+/*DHX:Depend dhtmlx.js*/
+
+dhtmlx.ui.Map = function(key){
+ this.name = "Map";
+ this._id = "map_"+dhtmlx.uid();
+ this._key = key;
+ this._map = [];
+};
+dhtmlx.ui.Map.prototype = {
+ addRect: function(id,points,userdata) {
+ this._createMapArea(id,"RECT",points,userdata);
+ },
+ addPoly: function(id,points) {
+ this._createMapArea(id,"POLY",points);
+ },
+ _createMapArea:function(id,shape,coords,userdata){
+ var extra_data = "";
+ if(arguments.length==4)
+ extra_data = "userdata='"+userdata+"'";
+ this._map.push("<area "+this._key+"='"+id+"' shape='"+shape+"' coords='"+coords.join()+"' "+extra_data+"></area>");
+ },
+ 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="<map id='"+this._id+"' name='"+this._id+"'>"+this._map.join("\n")+"</map><img "+src+" class='dhx_map_img' usemap='#"+this._id+"'>";
+
+ obj._htmlmap = d; //for clearing routine
+
+ this._map = [];
+ }
+};
+
+
+/* DHX DEPEND FROM FILE 'ext/chart/chart_base.js'*/
+
+
+/*DHX:Depend map.js*/
+dhtmlx.chart = {};
+
+
+/* DHX DEPEND FROM FILE 'ext/chart/chart_area.js'*/
+
+
+/*DHX:Depend ext/chart/chart_base.js*/
+dhtmlx.chart.area = {
+ /**
+ * renders an area chart
+ * @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
+ * @param: sIndex - index of drawing chart
+ */
+ pvt_render_area:function(ctx, data, point0, point1, sIndex, map){
+
+ var params = this._calculateParametersOfLineChart(ctx,data,point0,point1,sIndex);
+
+ /*the value that defines the map area position*/
+ var areaPos = Math.floor(params.cellWidth/2);
+
+ /*drawing all items*/
+ if (data.length) {
+
+ ctx.globalAlpha = this._settings.alpha.call(this,data[0]);
+ ctx.fillStyle = this._settings.color.call(this,data[0]);
+
+ /*the position of the first item*/
+ var y0 = this._getYPointOfLineChart(data[0],point0,point1,params);
+ var x0 = (this._settings.offset?point0.x+params.cellWidth*0.5:point0.x);
+ ctx.beginPath();
+ ctx.moveTo(x0,point1.y);
+ ctx.lineTo(x0,y0);
+
+ /*creates map area*/
+ map.addRect(data[0].id,[x0-areaPos,y0-areaPos,x0+areaPos,y0+areaPos]);
+ /*item label*/
+ if(!this._settings.yAxis)
+ this.renderTextAt(false, (!this._settings.offset?false:true), x0, y0-this._settings.labelOffset, this._settings.label(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 xi = x0+ Math.floor(params.cellWidth*i) - 0.5;
+ var yi = this._getYPointOfLineChart(data[i],point0,point1,params);
+ ctx.lineTo(xi,yi);
+ /*creates map area*/
+ map.addRect(data[i].id,[xi-areaPos,yi-areaPos,xi+areaPos,yi+areaPos]);
+ /*item label*/
+ if(!this._settings.yAxis)
+ this.renderTextAt(false, (!this._settings.offset&&i==(data.length-1)?"left":"center"), xi, yi-this._settings.labelOffset, this._settings.label(data[i]));
+ }
+ ctx.lineTo(x0+Math.floor(params.cellWidth*[data.length-1]),point1.y);
+ ctx.lineTo(x0,point1.y);
+ ctx.fill();
+ }
+ }
+};
+dhtmlx.chart.stackedArea ={
+ /**
+ * renders an area chart
+ * @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
+ * @param: sIndex - index of drawing chart
+ */
+ pvt_render_stackedArea:function(ctx, data, point0, point1, sIndex, map){
+
+ var params = this._calculateParametersOfLineChart(ctx,data,point0,point1,sIndex);
+
+ /*the value that defines the map area position*/
+ var areaPos = Math.floor(params.cellWidth/2);
+
+ var y1 = [];
+
+ /*drawing all items*/
+ if (data.length) {
+
+ ctx.globalAlpha = this._settings.alpha.call(this,data[0]);
+ ctx.fillStyle = this._settings.color.call(this,data[0]);
+
+ /*for the 2nd, 3rd, etc. series*/
+ var y01 = (sIndex?data[0].$startY:point1.y);
+
+ /*the position of the first item*/
+ var x0 = (this._settings.offset?point0.x+params.cellWidth*0.5:point0.x);
+ var y02 = this._getYPointOfLineChart(data[0],point0,point1,params)-(sIndex?(point1.y-y01):0);
+
+ y1[0] = y02;
+
+ ctx.beginPath();
+ ctx.moveTo(x0,y01);
+ ctx.lineTo(x0,y02);
+
+ /*creates map area*/
+ map.addRect(data[0].id,[x0-areaPos,y02-areaPos,x0+areaPos,y02+areaPos]);
+ /*item label*/
+ if(!this._settings.yAxis)
+ this.renderTextAt(false, true, x0, y02-this._settings.labelOffset, this._settings.label(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 xi = x0+ Math.floor(params.cellWidth*i) - 0.5;
+ var yi2 = this._getYPointOfLineChart(data[i],point0,point1,params)-(sIndex?(point1.y-data[i].$startY):0);
+
+ y1[i] = yi2;
+
+ ctx.lineTo(xi,yi2);
+ /*creates map area*/
+ map.addRect(data[i].id,[xi-areaPos,yi2-areaPos,xi+areaPos,yi2+areaPos]);
+ /*item label*/
+ if(!this._settings.yAxis)
+ this.renderTextAt(false, true, xi, yi2-this._settings.labelOffset, this._settings.label(data[i]));
+ }
+ ctx.lineTo(x0+Math.floor(params.cellWidth*[data.length-1]),y01);
+ /*drawing lines of the lower part*/
+ if(sIndex){
+ for(var i=data.length-1; i >=0 ;i--){
+ var xi = x0+ Math.floor(params.cellWidth*i) - 0.5;
+ var yi1 = data[i].$startY;
+ ctx.lineTo(xi,yi1);
+ }
+ }
+ else ctx.lineTo(x0+ Math.floor(params.cellWidth*(length-1)) - 0.5,y01);
+ ctx.lineTo(x0,y01);
+ ctx.fill();
+ for(var i=0; i < data.length;i ++){
+ data[i].$startY = y1[i];
+ }
+ }
+ }
+};
+
+
+
+/* DHX DEPEND FROM FILE 'ext/chart/chart_spline.js'*/
+
+
+/*DHX:Depend ext/chart/chart_base.js*/
+dhtmlx.chart.spline = {
+ /**
+ * renders a spline chart
+ * @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
+ * @param: sIndex - index of drawing chart
+ */
+ pvt_render_spline:function(ctx, data, point0, point1, sIndex, map){
+
+ var params = this._calculateParametersOfLineChart(ctx,data,point0,point1,sIndex);
+
+ /*the value that defines the map area position*/
+ var areaPos = Math.floor(params.cellWidth/2);
+
+ /*array of all points*/
+ var items = [];
+
+ /*drawing all items*/
+ if (data.length) {
+
+ /*getting all points*/
+ var x0 = (this._settings.offset?point0.x+params.cellWidth*0.5:point0.x);
+ for(var i=0; i < data.length;i ++){
+ var x = ((!i)?x0:Math.floor(params.cellWidth*i) - 0.5 + x0);
+ var y = this._getYPointOfLineChart(data[i],point0,point1,params);
+ items.push({x:x,y:y});
+ }
+ var sparam = this._getSplineParameters(items);
+
+ for(var i =0; i< items.length-1; i++){
+ var x1 = items[i].x;
+ var y1 = items[i].y;
+ var x2 = items[i+1].x;
+ var y2 = items[i+1].y;
+
+
+ for(var j = x1; j < x2; j++)
+ this._drawLine(ctx,j,this._getSplineYPoint(j,x1,i,sparam.a,sparam.b,sparam.c,sparam.d),j+1,this._getSplineYPoint(j+1,x1,i,sparam.a,sparam.b,sparam.c,sparam.d),this._settings.line.color(data[i]),this._settings.line.width);
+ this._drawLine(ctx,x2-1,this._getSplineYPoint(j,x1,i,sparam.a,sparam.b,sparam.c,sparam.d),x2,y2,this._settings.line.color(data[i]),this._settings.line.width);
+ this._drawItemOfLineChart(ctx,x1,y1,data[i],this._settings.label(data[i]));
+ }
+ this._drawItemOfLineChart(ctx,x2,y2,data[i],this._settings.label(data[i]));
+ }
+ },
+ /*gets spline parameter*/
+ _getSplineParameters:function(points){
+ var h,u,v,s,a,b,c,d,n;
+ h = []; m = [];
+ n = points.length;
+
+ for(var i =0; i<n-1;i++){
+ h[i] = points[i+1].x - points[i].x;
+ m[i] = (points[i+1].y - points[i].y)/h[i];
+ }
+ u = []; v = [];
+ u[0] = 0;
+ u[1] = 2*(h[0] + h[1]);
+ v[0] = 0;
+ v[1] = 6*(m[1] - m[0]);
+ for(var i =2; i < n-1; i++){
+ u[i] = 2*(h[i-1]+h[i]) - h[i-1]*h[i-1]/u[i-1];
+ v[i] = 6*(m[i]-m[i-1]) - h[i-1]*v[i-1]/u[i-1];
+ }
+
+ s = [];
+ s[n-1] = s[0] = 0;
+ for(var i = n -2; i>=1; i--)
+ s[i] = (v[i] - h[i]*s[i+1])/u[i];
+
+ a = []; b = []; c = []; d = [];
+
+ for(var i =0; i<n-1;i++){
+ a[i] = points[i].y;
+ b[i] = - h[i]*s[i+1]/6 - h[i]*s[i]/3 + (points[i+1].y-points[i].y)/h[i];
+ c[i] = s[i]/2;
+ d[i] = (s[i+1] - s[i])/(6*h[i]);
+ }
+ return {a:a,b:b,c:c,d:d};
+ },
+ /*returns the y position of the spline point */
+ _getSplineYPoint:function(x,xi,i,a,b,c,d){
+ return a[i] + (x - xi)*(b[i] + (x-xi)*(c[i]+(x-xi)*d[i]));
+ }
+};
+
+
+/* DHX DEPEND FROM FILE 'ext/chart/chart_barh.js'*/
+
+
+/*DHX:Depend ext/chart/chart_base.js*/
+dhtmlx.chart.barH = {
+ /**
+ * 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
+ * @param: sIndex - index of drawing chart
+ */
+ pvt_render_barH:function(ctx, data, point0, point1, sIndex, map){
+ var maxValue,minValue;
+ /*necessary if maxValue - minValue < 0*/
+ var valueFactor;
+ /*maxValue - minValue*/
+ var relValue;
+
+ var total_width = point1.x-point0.x;
+
+ var yax = !!this._settings.yAxis;
+ var xax = !!this._settings.xAxis;
+
+ var limits = this._getLimits("h");
+ maxValue = limits.max;
+ minValue = limits.min;
+
+ /*an available width for one bar*/
+ var cellWidth = Math.floor((point1.y-point0.y)/data.length);
+
+ /*draws x and y scales*/
+ if(!sIndex)
+ this._drawHScales(ctx,data,point0, point1,minValue,maxValue,cellWidth);
+
+ /*necessary for automatic scale*/
+ if(yax){
+ maxValue = parseFloat(this._settings.xAxis.end);
+ minValue = parseFloat(this._settings.xAxis.start);
+ }
+
+ /*unit calculation (bar_height = value*unit)*/
+ var relativeValues = this._getRelativeValue(minValue,maxValue);
+ relValue = relativeValues[0];
+ valueFactor = relativeValues[1];
+
+ var unit = (relValue?total_width/relValue:10);
+ if(!yax){
+ /*defines start value for better representation of small values*/
+ var startValue = 10;
+ unit = (relValue?(total_width-startValue)/relValue:10);
+ }
+
+
+ /*a real bar width */
+ var barWidth = parseInt(this._settings.width,10);
+ if((barWidth*this._series.length+4)>cellWidth) barWidth = cellWidth/this._series.length-4;
+ /*the half of distance between bars*/
+ var barOffset = Math.floor((cellWidth - barWidth*this._series.length)/2);
+ /*the radius of rounding in the top part of each bar*/
+ var radius = (typeof this._settings.radius!="undefined"?parseInt(this._settings.radius,10):Math.round(barWidth/5));
+
+ var inner_gradient = false;
+ var gradient = this._settings.gradient;
+
+ if (gradient&&typeof(gradient) != "function"){
+ inner_gradient = gradient;
+ gradient = false;
+ } else if (gradient){
+ gradient = ctx.createLinearGradient(point0.x,point0.y,point1.x,point0.y);
+ this._settings.gradient(gradient);
+ }
+ var scaleY = 0;
+ /*draws a black line if the horizontal scale isn't defined*/
+ if(!yax){
+ this._drawLine(ctx,point0.x-0.5,point0.y,point0.x-0.5,point1.y,"#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 = point0.x;
+ var y0 = point0.y+ barOffset + i*cellWidth+(barWidth+1)*sIndex;
+
+ 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._setBarHPoints(ctx,x0,y0,barWidth,radius,unit,value,0);
+ ctx.lineTo(x0,0);
+ ctx.fill();
+
+ ctx.fillStyle = "#000000";
+ ctx.globalAlpha = 0.37;
+ ctx.beginPath();
+ this._setBarHPoints(ctx,x0,y0,barWidth,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._setBarHPoints(ctx,x0,y0,barWidth,radius,unit,value,(this._settings.border?1:0));
+ if (gradient&&!inner_gradient) ctx.lineTo(point0.x+total_width,y0+(this._settings.border?1:0)); //fix gradient sphreading
+ ctx.fill();
+ ctx.globalAlpha = 1;
+
+ if (inner_gradient!=false){
+ var gradParam = this._setBarGradient(ctx,point0.x,y0+barWidth,point0.x+unit*value+2,y0,inner_gradient,color,"x");
+ ctx.fillStyle = gradParam.gradient;
+ ctx.beginPath();
+ var points = this._setBarHPoints(ctx,x0,y0+gradParam.offset,barWidth-gradParam.offset*2,radius,unit,value,gradParam.offset);
+ ctx.fill();
+ ctx.globalAlpha = 1;
+ }
+
+
+ /*sets a bar label*/
+ this.renderTextAt("middle",false,points[0]+3, parseInt(y0+(points[1]-y0)/2,10), this._settings.label(data[i]));
+ /*defines a map area for a bar*/
+ map.addRect(data[i].id,[x0,y0,points[0],points[1]],sIndex);
+ }
+ },
+ /**
+ * 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)
+ */
+ _setBarHPoints: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 sinA = (radius-unit*value)/radius;
+ angle_corr = -Math.asin(sinA)+Math.PI/2;
+ }
+ /*start*/
+ ctx.moveTo(x0,y0+offset);
+ /*start of left rounding*/
+ var x1 = x0 + unit*value - radius - (radius?0:offset);
+ if(radius<unit*value)
+ ctx.lineTo(x1,y0+offset);
+ /*left rounding*/
+ var y2 = y0 + radius;
+ if (radius)
+ ctx.arc(x1,y2,radius-offset,-Math.PI/2+angle_corr,0,false);
+ /*start of right rounding*/
+ var y3 = y0 + barWidth - radius - (radius?0:offset);
+ var x3 = x1 + radius - (radius?offset:0);
+ ctx.lineTo(x3,y3);
+ /*right rounding*/
+ var x4 = x1;
+ if (radius)
+ ctx.arc(x4,y3,radius-offset,0,Math.PI/2-angle_corr,false);
+ /*bottom right point*/
+ var y5 = y0 + barWidth-offset;
+ ctx.lineTo(x0,y5);
+ /*line to the start point*/
+ ctx.lineTo(x0,y0+offset);
+ // ctx.lineTo(x0,0); //IE fix!
+ return [x3,y5];
+ },
+ _drawHScales:function(ctx,data,point0,point1,start,end,cellWidth){
+ this._drawHXAxis(ctx,data,point0,point1,start,end);
+ this._drawHYAxis(ctx,data,point0,point1,cellWidth);
+ },
+ _drawHYAxis:function(ctx,data,point0,point1,cellWidth){
+ if (!this._settings.yAxis) return;
+
+ var x0 = point0.x-0.5;
+ var y0 = point1.y+0.5;
+ var y1 = point0.y;
+
+ this._drawLine(ctx,x0,y0,x0,y1,this._settings.yAxis.color,1);
+
+ for(var i=0; i < data.length;i ++){
+
+ /*scale labels*/
+ this.renderTextAt("middle",0,0,y1+cellWidth/2+i*cellWidth,
+ this._settings.yAxis.template(data[i]),
+ "dhx_axis_item_y",point0.x-5
+ );
+ }
+ this._setYAxisTitle(point0,point1);
+ },
+ _drawHXAxis:function(ctx,data,point0,point1,start,end){
+ var step;
+ var scaleParam= {};
+ var axis = this._settings.xAxis;
+ if (!axis) return;
+
+ var y0 = point1.y+0.5;
+ var x0 = point0.x-0.5;
+ var x1 = point1.x-0.5;
+
+ this._drawLine(ctx,x0,y0,x1,y0,axis.color,1);
+
+ if(axis.step)
+ step = parseFloat(axis.step);
+
+ if(typeof axis.step =="undefined"||typeof axis.start=="undefined"||typeof axis.end =="undefined"){
+ scaleParam = this._calculateScale(start,end);
+ start = scaleParam.start;
+ end = scaleParam.end;
+ step = scaleParam.step;
+ this._settings.xAxis.end = end;
+ this._settings.xAxis.start = start;
+ this._settings.xAxis.step = step;
+ };
+
+ if(step===0) return;
+ var stepHeight = (x1-x0)*step/(end-start);
+ var c = 0;
+ for(var i = start; i<=end; i += step){
+ if(scaleParam.fixNum) i = parseFloat((new Number(i)).toFixed(scaleParam.fixNum));
+ var xi = Math.floor(x0+c*stepHeight)+ 0.5;/*canvas line fix*/
+ if(i!=start &&axis.lines)
+ this._drawLine(ctx,xi,y0,xi,point0.y,this._settings.xAxis.color,0.2);
+ this.renderTextAt(false, true,xi,y0+2,axis.template(i.toString()),"dhx_axis_item_x");
+ c++;
+ };
+ this.renderTextAt(true, false, x0,point1.y+this._settings.padding.bottom-3,
+ this._settings.xAxis.title,
+ "dhx_axis_title_x",
+ point1.x - point0.x
+ );
+ /*the right border in lines in scale are enabled*/
+ if (!axis.lines) return;
+ this._drawLine(ctx,x0,point0.y-0.5,x1,point0.y-0.5,this._settings.xAxis.color,0.2);
+ }
+
+};
+
+
+
+/* DHX DEPEND FROM FILE 'ext/chart/chart_stackedbarh.js'*/
+
+
+/*DHX:Depend ext/chart/chart_base.js*/
+/*DHX:Depend ext/chart/chart_barh.js*/
+
+dhtmlx.assert(dhtmlx.chart.barH);
+dhtmlx.chart.stackedBarH = {
+/**
+ * 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
+ * @param: sIndex - index of drawing chart
+ * @param: map - map object
+ */
+ pvt_render_stackedBarH:function(ctx, data, point0, point1, sIndex, map){
+ var maxValue,minValue;
+ /*necessary if maxValue - minValue < 0*/
+ var valueFactor;
+ /*maxValue - minValue*/
+ var relValue;
+
+ var total_width = point1.x-point0.x;
+
+ var yax = !!this._settings.yAxis;
+ var xax = !!this._settings.xAxis;
+
+ var limits = this._getStackedLimits(data);
+ maxValue = limits.max;
+ minValue = limits.min;
+
+ /*an available width for one bar*/
+ var cellWidth = Math.floor((point1.y-point0.y)/data.length);
+
+ /*draws x and y scales*/
+ if(!sIndex)
+ this._drawHScales(ctx,data,point0, point1,minValue,maxValue,cellWidth);
+
+ /*necessary for automatic scale*/
+ if(yax){
+ maxValue = parseFloat(this._settings.xAxis.end);
+ minValue = parseFloat(this._settings.xAxis.start);
+ }
+
+ /*unit calculation (bar_height = value*unit)*/
+ var relativeValues = this._getRelativeValue(minValue,maxValue);
+ relValue = relativeValues[0];
+ valueFactor = relativeValues[1];
+
+ var unit = (relValue?total_width/relValue:10);
+ if(!yax){
+ /*defines start value for better representation of small values*/
+ var startValue = 10;
+ unit = (relValue?(total_width-startValue)/relValue:10);
+ }
+
+ /*a real bar width */
+ var barWidth = parseInt(this._settings.width,10);
+ if((barWidth+4)>cellWidth) barWidth = cellWidth-4;
+ /*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 = 0;
+
+ var inner_gradient = false;
+ var gradient = this._settings.gradient;
+
+ var inner_gradient = false;
+ var gradient = this._settings.gradient;
+ if (gradient){
+ inner_gradient = true;
+ }
+ var scaleY = 0;
+ /*draws a black line if the horizontal scale isn't defined*/
+ if(!yax){
+ this._drawLine(ctx,point0.x-0.5,point0.y,point0.x-0.5,point1.y,"#000000",1); //hardcoded color!
+ }
+
+ for(var i=0; i < data.length;i ++){
+
+ if(!sIndex)
+ data[i].$startX = point0.x;
+
+ var value = parseFloat(this._settings.value(data[i]));
+ if(value>maxValue) value = maxValue;
+ value -= minValue;
+ value *= valueFactor;
+
+ /*start point (bottom left)*/
+ var x0 = point0.x;
+ var y0 = point0.y+ barOffset + i*cellWidth;
+
+ /*for the 2nd, 3rd, etc. series*/
+ if(sIndex)
+ x0 = data[i].$startX;
+
+ 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 = this._settings.color.call(this,data[i]);
+
+ /*drawing the gradient border of a bar*/
+ if(this._settings.border){
+ ctx.beginPath();
+ ctx.fillStyle = color;
+ this._setBarHPoints(ctx,x0,y0,barWidth,radius,unit,value,0);
+ ctx.lineTo(x0,0);
+ ctx.fill();
+
+ ctx.fillStyle = "#000000";
+ ctx.globalAlpha = 0.37;
+ ctx.beginPath();
+ this._setBarHPoints(ctx,x0,y0,barWidth,radius,unit,value,0);
+ ctx.fill();
+ }
+ ctx.globalAlpha = 1;
+ /*drawing bar body*/
+ ctx.globalAlpha = this._settings.alpha.call(this,data[i]);
+ ctx.fillStyle = this._settings.color.call(this,data[i]);
+ ctx.beginPath();
+ var points = this._setBarHPoints(ctx,x0,y0,barWidth,radius,unit,value,(this._settings.border?1:0));
+ if (gradient&&!inner_gradient) ctx.lineTo(point0.x+total_width,y0+(this._settings.border?1:0)); //fix gradient sphreading
+ ctx.fill();
+
+ if (inner_gradient!=false){
+ var gradParam = this._setBarGradient(ctx,x0,y0+barWidth,x0,y0,inner_gradient,color,"x")
+ ctx.fillStyle = gradParam.gradient;
+ ctx.beginPath();
+ var points = this._setBarHPoints(ctx,x0,y0, barWidth,radius,unit,value,0);
+ ctx.fill();
+ ctx.globalAlpha = 1;
+ }
+
+ /*sets a bar label*/
+ this.renderTextAt("middle",true,data[i].$startX+(points[0]-data[i].$startX)/2-1, y0+(points[1]-y0)/2, this._settings.label(data[i]));
+ /*defines a map area for a bar*/
+ map.addRect(data[i].id,[data[i].$startX,y0,points[0],points[1]],sIndex);
+ /*the start position for the next series*/
+ data[i].$startX = points[0];
+ }
+ }
+}
+
+
+/* DHX DEPEND FROM FILE 'ext/chart/chart_stackedbar.js'*/
+
+
+/*DHX:Depend ext/chart/chart_base.js*/
+dhtmlx.chart.stackedBar = {
+ /**
+ * 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
+ * @param: sIndex - index of drawing chart
+ */
+ pvt_render_stackedBar:function(ctx, data, point0, point1, sIndex, map){
+ var maxValue,minValue;
+ /*necessary if maxValue - minValue < 0*/
+ var valueFactor;
+ /*maxValue - minValue*/
+ var relValue;
+
+ var total_height = point1.y-point0.y;
+
+ var yax = !!this._settings.yAxis;
+ var xax = !!this._settings.xAxis;
+
+ var limits = this._getStackedLimits(data);
+ maxValue = limits.max;
+ minValue = limits.min;
+
+ /*an available width for one bar*/
+ var cellWidth = Math.floor((point1.x-point0.x)/data.length);
+
+ /*draws x and y scales*/
+ if(!sIndex)
+ this._drawScales(ctx,data,point0, point1,minValue,maxValue,cellWidth);
+
+ /*necessary for automatic scale*/
+ if(yax){
+ maxValue = parseFloat(this._settings.yAxis.end);
+ minValue = parseFloat(this._settings.yAxis.start);
+ }
+
+ /*unit calculation (bar_height = value*unit)*/
+ var relativeValues = this._getRelativeValue(minValue,maxValue);
+ relValue = relativeValues[0];
+ valueFactor = relativeValues[1];
+
+ var unit = (relValue?total_height/relValue:10);
+
+ /*a real bar width */
+ var barWidth = parseInt(this._settings.width,10);
+ if(barWidth+4 > cellWidth) barWidth = cellWidth-4;
+ /*the half of distance between bars*/
+ var barOffset = Math.floor((cellWidth - barWidth)/2);
+
+
+ var inner_gradient = (this._settings.gradient?this._settings.gradient:false);
+
+ var scaleY = 0;
+ /*draws a black line if the horizontal scale isn't defined*/
+ if(!xax){
+ //scaleY = y-bottomPadding;
+ this._drawLine(ctx,point0.x,point1.y+0.5,point1.x,point1.y+0.5,"#000000",1); //hardcoded color!
+ }
+
+ for(var i=0; i < data.length;i ++){
+ var value = parseFloat(this._settings.value(data[i]));
+ if(!value) continue;
+
+ /*adjusts the first tab to the scale*/
+ if(!sIndex)
+ value -= minValue;
+
+ value *= valueFactor;
+
+ /*start point (bottom left)*/
+ var x0 = point0.x + barOffset + i*cellWidth;
+ var y0 = point1.y;
+
+ /*for the 2nd, 3rd, etc. series*/
+ if(sIndex)
+ y0 = data[i].$startY;
+
+ /*the max height limit*/
+ if(y0 < (point0.y+1)) continue;
+
+ if(value<0||(this._settings.yAxis&&value===0)){
+ this.renderTextAt(true, true, x0+Math.floor(barWidth/2),y0,this._settings.label(data[i]));
+ continue;
+ }
+
+ var color = this._settings.color.call(this,data[i]);
+
+ /*drawing the gradient border of a bar*/
+ if(this._settings.border){
+ ctx.beginPath();
+ ctx.fillStyle = color;
+ this._setStakedBarPoints(ctx,x0-1,y0,barWidth+2,unit,value,0,point0.y);
+ ctx.lineTo(x0,y0);
+ ctx.fill();
+
+ ctx.fillStyle = "#000000";
+ ctx.globalAlpha = 0.37;
+ ctx.beginPath();
+ this._setStakedBarPoints(ctx,x0-1,y0,barWidth+2,unit,value,0,point0.y);
+ ctx.fill();
+ }
+
+ /*drawing bar body*/
+ ctx.globalAlpha = this._settings.alpha.call(this,data[i]);
+ ctx.fillStyle = this._settings.color.call(this,data[i]);
+ ctx.beginPath();
+ var points = this._setStakedBarPoints(ctx,x0,y0,barWidth,unit,value,(this._settings.border?1:0),point0.y);
+ ctx.fill();
+ ctx.globalAlpha = 1;
+
+ /*gradient*/
+ if (inner_gradient){
+ var gradParam = this._setBarGradient(ctx,x0,y0,x0+barWidth,points[1],inner_gradient,color,"y");
+ ctx.fillStyle = gradParam.gradient;
+ ctx.beginPath();
+ var points = this._setStakedBarPoints(ctx,x0+gradParam.offset,y0,barWidth-gradParam.offset*2,unit,value,(this._settings.border?1:0),point0.y);
+ ctx.fill();
+ ctx.globalAlpha = 1;
+ }
+
+ /*sets a bar label*/
+ this.renderTextAt(false, true, x0+Math.floor(barWidth/2),(points[1]+(y0-points[1])/2)-7,this._settings.label(data[i]));
+ /*defines a map area for a bar*/
+ map.addRect(data[i].id,[x0,points[1],points[0],(data[i].$startY||y0)],sIndex);
+
+ /*the start position for the next series*/
+ data[i].$startY = (this._settings.border?(points[1]+1):points[1]);
+ }
+ },
+ /**
+ * 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)
+ * @param: minY - the minimum y position for the bars ()
+ */
+ _setStakedBarPoints:function(ctx,x0,y0,barWidth,unit,value,offset,minY){
+ /*start*/
+ ctx.moveTo(x0,y0);
+ /*start of left rounding*/
+ var y1 = y0 - unit*value+offset;
+ /*maximum height limit*/
+ if(y1<minY)
+ y1 = minY;
+ ctx.lineTo(x0,y1);
+ var x3 = x0 + barWidth;
+ var y3 = y1;
+ ctx.lineTo(x3,y3);
+ /*right rounding*/
+ var y4 = y1;
+ /*bottom right point*/
+ var x5 = x0 + barWidth;
+ ctx.lineTo(x5,y0);
+ /*line to the start point*/
+ ctx.lineTo(x0,y0);
+ // ctx.lineTo(x0,0); //IE fix!
+ return [x5,y3-2*offset];
+ }
+};
+
+
+
+/* DHX DEPEND FROM FILE 'ext/chart/chart_line.js'*/
+
+
+/*DHX:Depend ext/chart/chart_base.js*/
+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
+ * @param: sIndex - index of drawing chart
+ */
+ pvt_render_line:function(ctx, data, point0, point1, sIndex, map){
+
+ var params = this._calculateParametersOfLineChart(ctx,data,point0,point1,sIndex);
+
+ /*the value that defines the map area position*/
+ var areaPos = Math.floor(params.cellWidth/2);
+
+ /*drawing all items*/
+ if (data.length) {
+ /*gets the vertical coordinate of an item*/
+
+ /*the position of the first item*/
+ var y1 = this._getYPointOfLineChart(data[0],point0,point1,params);
+ var x1 = (this._settings.offset?point0.x+params.cellWidth*0.5:point0.x);
+ var x0 = x1;
+ /*drawing the previous item and the line between to items*/
+ for(var i=1; i <= data.length;i ++){
+
+ /*horizontal positions of the item (0.5 - the fix for line width)*/
+ //var x1 = Math.floor(params.cellWidth*(i-0.5)) - 0.5 + point0.x;
+ var x2 = Math.floor(params.cellWidth*i) - 0.5 + x0;
+
+ /*a line between items*/
+ if (data.length!=i){
+ var y2 = this._getYPointOfLineChart(data[i],point0,point1,params);
+ this._drawLine(ctx,x1,y1,x2,y2,this._settings.line.color(data[i-1]),this._settings.line.width);
+ }
+
+ /*draws prevous item*/
+ this._drawItemOfLineChart(ctx,x1,y1,data[i-1],!!this._settings.offset);
+
+ /*creates map area*/
+ map.addRect(data[i-1].id,[x1-areaPos,y1-areaPos,x1+areaPos,y1+areaPos]);
+
+ y1=y2;
+ x1=x2;
+ }
+ }
+ },
+ /**
+ * 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
+ * @param: label - (boolean) defines wherether label needs being drawn
+ */
+ _drawItemOfLineChart:function(ctx,x0,y0,obj,label){
+ 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*/
+ if(label)
+ this.renderTextAt(false, true, x0,y0-R-this._settings.labelOffset,this._settings.label(obj));
+ },
+ /**
+ * gets the vertical position of the item
+ * @param: data - data object
+ * @param: y0 - the y position of chart start
+ * @param: y1 - the y position of chart end
+ * @param: params - the object with elements: minValue, maxValue, unit, valueFactor (the value multiple of 10)
+ */
+ _getYPointOfLineChart: function(data,point0,point1,params){
+ var minValue = params.minValue;
+ var maxValue = params.maxValue;
+ var unit = params.unit;
+ var valueFactor = params.valueFactor;
+ /*the real value of an object*/
+ var value = this._settings.value(data);
+ /*a relative value*/
+ var v = (parseFloat(value) - minValue)*valueFactor;
+ if(!this._settings.yAxis)
+ v += params.startValue/unit;
+ /*a vertical coordinate*/
+ var y = point1.y - Math.floor(unit*v);
+ /*the limit of the minimum value is the minimum visible value*/
+ if(v<0)
+ y = point1.y;
+ /*the limit of the maximum value*/
+ if(value > maxValue)
+ y = point0.y;
+ /*the limit of the minimum value*/
+ if(value < minValue)
+ y = point1.y;
+ return y;
+ },
+ _calculateParametersOfLineChart: function(ctx,data,point0,point1,sIndex){
+ var params = {};
+
+ /*maxValue - minValue*/
+ var relValue;
+
+ /*available height*/
+ params.totalHeight = point1.y-point0.y;
+
+ /*a space available for a single item*/
+ //params.cellWidth = Math.round((point1.x-point0.x)/((!this._settings.offset&&this._settings.yAxis)?(data.length-1):data.length));
+ params.cellWidth = Math.round((point1.x-point0.x)/((!this._settings.offset)?(data.length-1):data.length));
+
+ /*scales*/
+ var yax = !!this._settings.yAxis;
+ var xax = !!this._settings.xAxis;
+
+ var limits = (this._settings.view.indexOf("stacked")!=-1?this._getStackedLimits(data):this._getLimits());
+ params.maxValue = limits.max;
+ params.minValue = limits.min;
+
+ /*draws x and y scales*/
+ if(!sIndex)
+ this._drawScales(ctx,data, point0, point1,params.minValue,params.maxValue,params.cellWidth);
+
+ /*necessary for automatic scale*/
+ if(yax){
+ params.maxValue = parseFloat(this._settings.yAxis.end);
+ params.minValue = parseFloat(this._settings.yAxis.start);
+ }
+
+ /*unit calculation (y_position = value*unit)*/
+ var relativeValues = this._getRelativeValue(params.minValue,params.maxValue);
+ relValue = relativeValues[0];
+ params.valueFactor = relativeValues[1];
+ params.unit = (relValue?params.totalHeight/relValue:10);
+
+ params.startValue = 0;
+ if(!yax){
+ /*defines start value for better representation of small values*/
+ params.startValue = (params.unit>10?params.unit:10);
+ params.unit = (relValue?(params.totalHeight - params.startValue)/relValue:10);
+ }
+ return params;
+ }
+};
+
+
+
+/* DHX DEPEND FROM FILE 'ext/chart/chart_bar.js'*/
+
+
+/*DHX:Depend ext/chart/chart_base.js*/
+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
+ * @param: sIndex - index of drawing chart
+ */
+ pvt_render_bar:function(ctx, data, point0, point1, sIndex, map){
+ var maxValue,minValue;
+ /*necessary if maxValue - minValue < 0*/
+ var valueFactor;
+ /*maxValue - minValue*/
+ var relValue;
+
+ var total_height = point1.y-point0.y;
+
+ var yax = !!this._settings.yAxis;
+ var xax = !!this._settings.xAxis;
+
+ var limits = this._getLimits();
+ maxValue = limits.max;
+ minValue = limits.min;
+
+ /*an available width for one bar*/
+ var cellWidth = Math.floor((point1.x-point0.x)/data.length);
+
+ /*draws x and y scales*/
+ if(!sIndex&&!(this._settings.origin!="auto"&&!yax)){
+ this._drawScales(ctx,data,point0, point1,minValue,maxValue,cellWidth);
+ }
+
+ /*necessary for automatic scale*/
+ if(yax){
+ maxValue = parseFloat(this._settings.yAxis.end);
+ minValue = parseFloat(this._settings.yAxis.start);
+ }
+
+ /*unit calculation (bar_height = value*unit)*/
+ var relativeValues = this._getRelativeValue(minValue,maxValue);
+ relValue = relativeValues[0];
+ valueFactor = relativeValues[1];
+
+ var unit = (relValue?total_height/relValue:relValue);
+ if(!yax&&!(this._settings.origin!="auto"&&xax)){
+ /*defines start value for better representation of small values*/
+ var startValue = 10;
+ unit = (relValue?(total_height-startValue)/relValue:startValue);
+ }
+ /*if yAxis isn't set, but with custom origin */
+ if(!sIndex&&(this._settings.origin!="auto"&&!yax)&&this._settings.origin>minValue){
+ this._drawXAxis(ctx,data,point0,point1,cellWidth,point1.y-unit*(this._settings.origin-minValue));
+ }
+
+ /*a real bar width */
+ var barWidth = parseInt(this._settings.width,10);
+ if(this._series&&(barWidth*this._series.length+4)>cellWidth) barWidth = cellWidth/this._series.length-4;
+ /*the half of distance between bars*/
+ var barOffset = Math.floor((cellWidth - barWidth*this._series.length)/2);
+ /*the radius of rounding in the top part of each bar*/
+ var radius = (typeof this._settings.radius!="undefined"?parseInt(this._settings.radius,10):Math.round(barWidth/5));
+
+ var inner_gradient = false;
+ var gradient = this._settings.gradient;
+
+ if(gradient && typeof(gradient) != "function"){
+ inner_gradient = gradient;
+ gradient = false;
+ } else if (gradient){
+ gradient = ctx.createLinearGradient(0,point1.y,0,point0.y);
+ this._settings.gradient(gradient);
+ }
+ var scaleY = 0;
+ /*draws a black line if the horizontal scale isn't defined*/
+ if(!xax){
+ this._drawLine(ctx,point0.x,point1.y+0.5,point1.x,point1.y+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 = point0.x + barOffset + i*cellWidth+(barWidth+1)*sIndex;
+ var y0 = point1.y;
+
+ if(value<0||(this._settings.yAxis&&value===0&&!(this._settings.origin!="auto"&&this._settings.origin>minValue))){
+ this.renderTextAt(true, true, x0+Math.floor(barWidth/2),y0,this._settings.label(data[i]));
+ continue;
+ }
+
+ /*takes start value into consideration*/
+ if(!yax&&!(this._settings.origin!="auto"&&xax)) value += startValue/unit;
+
+ var color = gradient||this._settings.color.call(this,data[i]);
+
+ /*drawing the gradient border of a bar*/
+ if(this._settings.border)
+ this._drawBarBorder(ctx,x0,y0,barWidth,minValue,radius,unit,value,color);
+
+ /*drawing bar body*/
+ ctx.globalAlpha = this._settings.alpha.call(this,data[i]);
+ var points = this._drawBar(ctx,point0,x0,y0,barWidth,minValue,radius,unit,value,color,gradient,inner_gradient);
+ ctx.globalAlpha = 1;
+
+ if (inner_gradient){
+ this._drawBarGradient(ctx,x0,y0,barWidth,minValue,radius,unit,value,color,inner_gradient);
+ }
+ /*sets a bar label*/
+ if(points[0]!=x0)
+ this.renderTextAt(false, true, x0+Math.floor(barWidth/2),points[1],this._settings.label(data[i]));
+ else
+ this.renderTextAt(true, true, x0+Math.floor(barWidth/2),points[3],this._settings.label(data[i]));
+ /*defines a map area for a bar*/
+ map.addRect(data[i].id,[x0,points[3],points[2],points[1]],sIndex);
+ }
+ },
+ _correctBarParams:function(ctx,x,y,value,unit,barWidth,minValue){
+ var xax = this._settings.xAxis;
+ var axisStart = y;
+ if(!!xax&&this._settings.origin!="auto" && (this._settings.origin>minValue)){
+ y -= (this._settings.origin-minValue)*unit;
+ axisStart = y;
+ value = value-(this._settings.origin-minValue);
+ if(value < 0){
+ value *= (-1);
+ ctx.translate(x+barWidth,y);
+ ctx.rotate(Math.PI);
+ x = 0;
+ y = 0;
+ }
+ y -= 0.5;
+ }
+
+ return {value:value,x0:x,y0:y,start:axisStart}
+ },
+ _drawBar:function(ctx,point0,x0,y0,barWidth,minValue,radius,unit,value,color,gradient,inner_gradient){
+ ctx.save();
+ ctx.fillStyle = color;
+ var p = this._correctBarParams(ctx,x0,y0,value,unit,barWidth,minValue);
+ var points = this._setBarPoints(ctx,p.x0,p.y0,barWidth,radius,unit,p.value,(this._settings.border?1:0));
+ if (gradient&&!inner_gradient) ctx.lineTo(p.x0+(this._settings.border?1:0),point0.y); //fix gradient sphreading
+ ctx.fill()
+ ctx.restore();
+ var x1 = p.x0;
+ var x2 = (p.x0!=x0?x0+points[0]:points[0]);
+ var y1 = (p.x0!=x0?(p.start-points[1]):y0);
+ var y2 = (p.x0!=x0?p.start:points[1]);
+ return [x1,y1,x2,y2];
+ },
+ _drawBarBorder:function(ctx,x0,y0,barWidth,minValue,radius,unit,value,color){
+ ctx.save();
+ var p = this._correctBarParams(ctx,x0,y0,value,unit,barWidth,minValue);
+
+ ctx.fillStyle = color;
+ this._setBarPoints(ctx,p.x0,p.y0,barWidth,radius,unit,p.value,0);
+ ctx.lineTo(p.x0,0);
+ ctx.fill()
+
+
+ ctx.fillStyle = "#000000";
+ ctx.globalAlpha = 0.37;
+
+ this._setBarPoints(ctx,p.x0,p.y0,barWidth,radius,unit,p.value,0);
+ ctx.fill()
+ ctx.restore();
+ },
+ _drawBarGradient:function(ctx,x0,y0,barWidth,minValue,radius,unit,value,color,inner_gradient){
+ ctx.save();
+ //y0 -= (dhtmlx._isIE?0:0.5);
+ var p = this._correctBarParams(ctx,x0,y0,value,unit,barWidth,minValue);
+ var gradParam = this._setBarGradient(ctx,p.x0,p.y0,p.x0+barWidth,p.y0-unit*p.value+2,inner_gradient,color,"y");
+ ctx.fillStyle = gradParam.gradient;
+ this._setBarPoints(ctx,p.x0+gradParam.offset,p.y0,barWidth-gradParam.offset*2,radius,unit,p.value,gradParam.offset);
+ ctx.fill()
+ ctx.restore();
+ },
+ /**
+ * 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)*/
+ ctx.beginPath();
+ //y0 = 0.5;
+ 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+offset,y0);
+ /*start of left rounding*/
+ var y1 = y0 - Math.floor(unit*value) + radius + (radius?0:offset);
+ if(radius<unit*value)
+ ctx.lineTo(x0+offset,y1);
+ /*left rounding*/
+ var x2 = x0 + radius;
+ if (radius)
+ ctx.arc(x2,y1,radius-offset,-Math.PI+angle_corr,-Math.PI/2,false);
+ /*start of right rounding*/
+ var x3 = x0 + barWidth - radius - (radius?0:offset);
+ var y3 = y1 - radius+(radius?offset:0);
+ ctx.lineTo(x3,y3);
+ /*right rounding*/
+ var y4 = y1;
+ if (radius)
+ ctx.arc(x3,y4,radius-offset,-Math.PI/2,0-angle_corr,false);
+ /*bottom right point*/
+ var x5 = x0 + barWidth-offset;
+ ctx.lineTo(x5,y0);
+ /*line to the start point*/
+ ctx.lineTo(x0+offset,y0);
+ // ctx.lineTo(x0,0); //IE fix!
+ return [x5,y3];
+ }
+};
+
+
+/* DHX DEPEND FROM FILE 'ext/chart/chart_pie.js'*/
+
+
+/*DHX:Depend ext/chart/chart_base.js*/
+dhtmlx.chart.pie = {
+ pvt_render_pie:function(ctx,data,x,y,sIndex,map){
+ this._renderPie(ctx,data,x,y,1,map);
+
+ },
+ /**
+ * renders a pie 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
+ * @param: ky - value from 0 to 1 that defines an angle of inclination (0<ky<1 - 3D chart)
+ */
+ _renderPie:function(ctx,data,point0,point1,ky,map){
+
+ var totalValue = 0;
+ var coord = this._getPieParameters(point0,point1);
+ /*pie radius*/
+ var radius = (this._settings.radius?this._settings.radius:coord.radius);
+ var maxValue = this.max(this._settings.value);
+ /*weighed values (the ratio of object value to total value)*/
+ var ratios = [];
+ /*real values*/
+ var values = [];
+ var prevSum = 0;
+
+ for(var i = 0; i < data.length;i++)
+ totalValue += parseFloat(this._settings.value(data[i]));
+
+ for(var i = 0; i < data.length;i++){
+ values[i] = parseFloat(this._settings.value(data[i]));
+ ratios[i] = Math.PI*2*(totalValue?((values[i]+prevSum)/totalValue):(1/data.length));
+ prevSum += values[i];
+ }
+ /*pie center*/
+ var x0 = (this._settings.x?this._settings.x:coord.x);
+ var y0 = (this._settings.y?this._settings.y:coord.y);
+ /*adds shadow to the 2D pie*/
+ if(ky==1&&this._settings.shadow)
+ this._addShadow(ctx,x0,y0,radius);
+
+ /*changes vertical position of the center according to 3Dpie cant*/
+ y0 = y0/ky;
+ /*the angle defines the 1st edge of the sector*/
+ var alpha0 = -Math.PI/2;
+ /*changes Canvas vertical scale*/
+ ctx.scale(1,ky);
+
+ for(var i = 0; i < data.length;i++){
+ if (!values[i]) continue;
+ /*drawing sector*/
+ ctx.lineWidth = 2;
+ ctx.beginPath();
+ ctx.moveTo(x0,y0);
+ /*the angle defines the 2nd edge of the sector*/
+ alpha1 = -Math.PI/2+ratios[i]-0.0001;
+ ctx.arc(x0,y0,radius,alpha0,alpha1,false);
+ ctx.lineTo(x0,y0);
+
+ var color = this._settings.color.call(this,data[i]);
+ ctx.fillStyle = color;
+
+ ctx.strokeStyle = this._settings.lineColor(data[i]);
+ ctx.stroke();
+ ctx.fill();
+
+ /*text that needs being displayed inside the sector*/
+ if(this._settings.pieInnerText)
+ this._drawSectorLabel(x0,y0,5*radius/6,alpha0,alpha1,ky,this._settings.pieInnerText(data[i],totalValue),true);
+ /*label outside the sector*/
+ if(this._settings.label)
+ this._drawSectorLabel(x0,y0,radius+this._settings.labelOffset,alpha0,alpha1,ky,this._settings.label(data[i]));
+ /*drawing lower part for 3D pie*/
+ if(ky!=1){
+ this._createLowerSector(ctx,x0,y0,alpha0,alpha1,radius,true);
+ ctx.fillStyle = "#000000";
+ ctx.globalAlpha = 0.2;
+ this._createLowerSector(ctx,x0,y0,alpha0,alpha1,radius,false);
+ ctx.globalAlpha = 1;
+ ctx.fillStyle = color;
+ }
+
+ /*creats map area (needed for events)*/
+ map.addSector(data[i].id,alpha0,alpha1,x0,y0,radius,ky);
+
+ alpha0 = alpha1;
+
+
+ }
+
+ /*adds radial gradient to a pie*/
+ if (this._settings.gradient){
+ var x1 = (ky!=1?x0+radius/3:x0);
+ var y1 = (ky!=1?y0+radius/3:y0);
+ this._showRadialGradient(ctx,x0,y0,radius,x1,y1);
+ }
+ ctx.scale(1,1/ky);
+ },
+ /**
+ * returns calculated pie parameters: center position and radius
+ * @param: x - the width of a container
+ * @param: y - the height of a container
+ */
+ _getPieParameters:function(point0,point1){
+ /*var offsetX = 0;
+ var offsetY = 0;
+ if(this._settings.legend &&this._settings.legend.layout!="x")
+ offsetX = this._settings.legend.width*(this._settings.legend.align=="right"?-1:1);
+ var x0 = (x + offsetX)/2;
+ if(this._settings.legend &&this._settings.legend.layout=="x")
+ offsetY = this._settings.legend.height*(this._settings.legend.valign=="bottom"?-1:1);
+ var y0 = (y+offsetY)/2;*/
+ var width = point1.x-point0.x;
+ var height = point1.y-point0.y;
+ var x0 = point0.x+width/2;
+ var y0 = point0.y+height/2
+ var radius = Math.min(width/2,height/2);
+ return {"x":x0,"y":y0,"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){
+ //correction need to be applied because of righ align
+ //we need to count right upper angle instead of left upper angle
+ corr_x = -labelWidth-corr_x+1;/*correction for label width*/
+ align = "right";
+ }
+ //for items in right lower sector
+ if(alpha<=3*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";
+ }
+};
+
+dhtmlx.chart.pie3D = {
+ pvt_render_pie3D:function(ctx,data,x,y,sIndex,map){
+ this._renderPie(ctx,data,x,y,this._settings.cant,map);
+ }
+}
+
+
+/* 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){
+ if (this._disabled) return;
+ //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";
+ },
+ disable:function(){
+ this._disabled = true;
+ },
+ enable:function(){
+ this._disabled = false;
+ },
+ 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
+ this._tree_store = false;
+};
+
+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];
+ },
+ _tree_parse:function(data){
+ if (data.item){ //FIXME
+ if (!(data.item instanceof Array))
+ data.item=[data.item];
+ for (var i=0; i < data.item.length; i++) {
+ var item = data.item[i];
+ var id = this.id(item);
+
+ data.item[i]=id;
+ this.pull[id]=item;
+ item.parent = data.id;
+ item.level = data.level+1;
+ this._tree_parse(item);
+ };
+ }
+ },
+ //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; i<recs.length; i++){
+ //get has of details for each record
+ var temp = this.driver.getDetails(recs[i]);
+ var id = this.id(temp); //generate ID for the record
+ if (!this.pull[id]){ //if such ID already exists - update instead of insert
+ this.order[j+from]=id;
+ j++;
+ }
+ this.pull[id]=temp;
+ if (this._tree_store){
+ temp.level = 1;
+ this._tree_parse(temp);
+ }
+ }
+
+ //for all not loaded data
+ for (var i=0; i < info._size; i++)
+ if (!this.order[i]){
+ var id = dhtmlx.uid();
+ var temp = {id:id, $template:"loading"}; //create fake records
+ this.pull[id]=temp;
+ this.order[i]=id;
+ }
+ this.callEvent("onStoreLoad",[this.driver, data]);
+ //repaint self after data loading
+ this.refresh();
+ },
+ //generate id for data object
+ id:function(data){
+ return data.id||(data.id=dhtmlx.uid());
+ },
+ //get data from hash by id
+ get:function(id){
+ return this.pull[id];
+ },
+ //assigns data by id
+ set:function(id,data){
+ this.pull[id]=data;
+ this.refresh();
+ },
+ //sends repainting signal
+ refresh:function(id){
+ if (id)
+ this.callEvent("onStoreUpdated",[id, this.pull[id], "update"]);
+ else
+ this.callEvent("onStoreUpdated",[null,null,null]);
+ },
+ //converts range IDs to array of all IDs between them
+ getRange:function(from,to){
+ if (!arguments.length){
+ //if indexes not provided - return all visible rows
+ from = this.min||0; to = Math.min((this.max||Infinity),(this.dataCount()-1));
+ } else{
+ from = this.indexById(from);
+ to = this.indexById(to);
+ if (from>to){ //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){
+ 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,Math.min(this.order.length, 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 < 0)
+ 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 == -1)
+ 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;
+
+ if (this.order.length){
+ var sorter = dhtmlx.sort.create(sort);
+ //get array of IDs
+ var neworder = this.getRange(this.first(), this.last());
+ 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; i<this.order.length; i++)
+ method.call((master||this), this.get(this.order[i]));
+ },
+ /*
+ map inner methods to some distant object
+ */
+ provideApi:function(target,eventable){
+
+ if (eventable){
+ this.mapEvent({
+ onbeforesort: target,
+ onaftersort: target,
+ onbeforeadd: target,
+ onafteradd: target,
+ onbeforedelete: target,
+ onafterdelete: target
+ });
+ }
+
+ var list = ["sort","add","remove","exists","idByIndex","indexById","get","set","refresh","dataCount","filter","next","previous","clearAll","first","last"];
+ for (var i=0; i < list.length; i++)
+ target[list[i]]=dhtmlx.methodPush(this,list[i]);
+
+ if (dhtmlx.assert_enabled())
+ this.assert_event(target);
+ }
+};
+
+dhtmlx.sort = {
+ create:function(config){
+ return dhtmlx.sort.dir(config.dir, dhtmlx.sort.by(config.by, config.as));
+ },
+ as:{
+ "int":function(a,b){
+ a = a*1; b=b*1;
+ return a>b?1:(a<b?-1:0);
+ },
+ "string_strict":function(a,b){
+ a = a.toString(); b=b.toString();
+ return a>b?1:(a<b?-1:0);
+ },
+ "string":function(a,b){
+ a = a.toString().toLowerCase(); b=b.toString().toLowerCase();
+ return a>b?1:(a<b?-1:0);
+ }
+ },
+ by:function(prop, method){
+ if (typeof method != "function")
+ method = dhtmlx.sort.as[method||"string"];
+ prop = dhtmlx.Template.setter(0,prop);
+ return function(a,b){
+ return method(prop(a),prop(b));
+ };
+ },
+ dir:function(prop, method){
+ if (prop == "asc")
+ return method;
+ return function(a,b){
+ return method(a,b)*-1;
+ };
+ }
+};
+
+
+/* DHX DEPEND FROM FILE 'group.js'*/
+
+
+/*DHX:Depend datastore.js*/
+/*DHX:Depend dhtmlx.js*/
+
+dhtmlx.Group = {
+ _init:function(){
+ dhtmlx.assert(this.data,"DataStore required for grouping");
+ this.data.attachEvent("onStoreLoad",dhtmlx.bind(function(){
+ if (this._settings.group)
+ this.group(this._settings.group,false);
+ },this));
+ this.attachEvent("onBeforeRender",dhtmlx.bind(function(data){
+ if (this._settings.sort){
+ data.block();
+ data.sort(this._settings.sort);
+ data.unblock();
+ }
+ },this));
+ this.attachEvent("onBeforeSort",dhtmlx.bind(function(){
+ this._settings.sort = null;
+ },this));
+ },
+ _init_group_data_event:function(data,master){
+ data.attachEvent("onClearAll",dhtmlx.bind(function(){
+ this.ungroup(false);
+ },master));
+ },
+ sum:function(property, data){
+ property = dhtmlx.Template.setter(0,property);
+
+ data = data || this.data;
+ var summ = 0;
+ data.each(function(obj){
+ summ+=property(obj)*1;
+ });
+ return summ;
+ },
+ min:function(property, data){
+ property = dhtmlx.Template.setter(0,property);
+
+ data = data || this.data;
+ var min = Infinity;
+ data.each(function(obj){
+ if (property(obj)*1 < min) min = property(obj)*1;
+ });
+ return min*1;
+ },
+ max:function(property, data){
+ property = dhtmlx.Template.setter(0,property);
+
+ data = data || this.data;
+ var max = -Infinity;
+ data.each(function(obj){
+ if (property(obj)*1 > 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.which||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.on_click){
+ dhtmlx.event(this._obj,"click",this._onClick,this);
+ dhtmlx.event(this._obj,"contextmenu",this._onContext,this);
+ }
+ if (this.on_dblclick)
+ dhtmlx.event(this._obj,"dblclick",this._onDblClick,this);
+ if (this.on_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.on_click,"ItemClick");
+ },
+ //inner ondblclick object handler
+ _onDblClick: function(e) {
+ return this._mouseEvent(e,this.on_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.on_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 && trg.getAttribute){ //if element with ID mark is not detected yet
+ id = trg.getAttribute(this._id); //check id of current one
+ if (id){
+ if (trg.getAttribute("userdata"))
+ this.callEvent("onLocateData",[id,trg]);
+ 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= {};
+ },
+ 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 hash 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)?"&":"?")+this.serialize(a1,rowId),"",function(t,x,xml){
+ loader.xml = dhtmlx.DataDriver.xml.checkResponse(t,x);
+ a2.afterUpdate(a2, null, null, null, loader);
+ });
+ else
+ dhtmlx.ajax().post(a3,this.serialize(a1,rowId),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;
+
+ var that = this.vs[this.av];
+ that.grid = new window[name](conf);
+
+ that.gridId = obj.id;
+ that.gridObj = obj;
+
+
+ that.grid.setSizes = function(){
+ if (this.resize) this.resize();
+ else this.render();
+ };
+
+ var method_name="_viewRestore";
+ return this.vs[this[method_name]()].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(){};
+
+
+
+/* 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; i<a.length; i++)
+ z[a[i].name]=a[i].value;
+ //map subtags
+ var flag=false;
+ var b=tag.childNodes;
+ var state = {};
+ for (var i=0; i<b.length; i++){
+ if (b[i].nodeType==1){
+ var name = b[i].tagName;
+ if (typeof z[name] != "undefined"){
+ if (!(z[name] instanceof Array))
+ z[name]=[z[name]];
+ z[name].push(this.tagToObject(b[i],{}));
+ }
+ else
+ z[b[i].tagName]=this.tagToObject(b[i],{}); //sub-object for complex subtags
+ flag=true;
+ }
+ }
+
+ if (!a.length && !flag)
+ return this.nodeValue(tag);
+ //each object will have its text content as "value" property
+ z.value = this.nodeValue(tag);
+ return z;
+ },
+ //get value of xml node
+ nodeValue:function(node){
+ if (node.firstChild)
+ return node.firstChild.data; //FIXME - long text nodes in FF not supported for now
+ return "";
+ },
+ //convert XML string to XML object
+ fromString:function(xmlString){
+ if (window.DOMParser) // FF, KHTML, Opera
+ return (new DOMParser()).parseFromString(xmlString,"text/xml");
+ if (window.ActiveXObject){ // IE, utf-8 only
+ temp=new ActiveXObject("Microsoft.xmlDOM");
+ temp.loadXML(xmlString);
+ return temp;
+ }
+ dhtmlx.error("Load from xml string is not supported");
+ },
+ //check is XML correct and try to reparse it if its invalid
+ checkResponse:function(text,xml){
+ if (xml && ( xml.firstChild && xml.firstChild.tagName != "parsererror") )
+ return xml;
+ //parsing as string resolves incorrect content type
+ //regexp removes whitespaces before xml declaration, which is vital for FF
+ var a=this.from_string(text.responseText.replace(/^[\s]+/,""));
+ if (a) return a;
+
+ dhtmlx.error("xml can't be parsed",text.responseText);
+ }
+};
+
+
+
+
+/* DHX DEPEND FROM FILE 'compatibility_grid.js'*/
+
+
+/*
+ Compatibility hack for loading data from the grid.
+ Provides new type of datasource - dhtmlxgrid
+
+*/
+
+/*DHX:Depend load.js*/
+
+dhtmlx.DataDriver.dhtmlxgrid={
+ _grid_getter:"_get_cell_value",
+ toObject:function(data){
+ this._grid = data;
+ return data;
+ },
+ getRecords:function(data){
+ return data.rowsBuffer;
+ },
+ getDetails:function(data){
+ var result = {};
+ for (var i=0; i < this._grid.getColumnsNum(); i++)
+ result["data"+i]=this._grid[this._grid_getter](data,i);
+
+ return result;
+ },
+ getInfo:function(data){
+ return {
+ _size:0,
+ _from:0
+ };
+ }
+};
+
+
+/* DHX DEPEND FROM FILE 'canvas.js'*/
+
+
+/*DHX:Depend thirdparty\excanvas*/
+/*DHX:Depend dhtmlx.js*/
+
+dhtmlx.Canvas = {
+ _init:function(){
+ this._canvas_labels = [];
+ },
+ _prepareCanvas:function(container){
+ //canvas has the same size as master object
+ this._canvas = dhtmlx.html.create("canvas",{ width:container.offsetWidth, height:container.offsetHeight });
+ container.appendChild(this._canvas);
+ //use excanvas in IE
+ if (!this._canvas.getContext){
+ if (dhtmlx._isIE){
+ dhtmlx.require("thirdparty/excanvas/excanvas.js"); //sync loading
+ G_vmlCanvasManager.init_(document);
+ G_vmlCanvasManager.initElement(this._canvas);
+ } else //some other not supported browser
+ dhtmlx.error("Canvas is not supported in the current browser");
+ }
+ return this._canvas;
+ },
+ getCanvas:function(context){
+ return (this._canvas||this._prepareCanvas(this._obj)).getContext(context||"2d");
+ },
+ _resizeCanvas:function(){
+ if (this._canvas){
+ this._canvas.setAttribute("width", this._canvas.parentNode.offsetWidth);
+ this._canvas.setAttribute("height", this._canvas.parentNode.offsetHeight);
+ }
+ },
+ renderText:function(x,y,text,css,w){
+ if (!text) return; //ignore empty text
+
+ var t = dhtmlx.html.create("DIV",{
+ "class":"dhx_canvas_text"+(css?(" "+css):""),
+ "style":"left:"+x+"px; top:"+y+"px;"
+ },text);
+ this._obj.appendChild(t);
+ this._canvas_labels.push(t); //destructor?
+ if (w)
+ t.style.width = w+"px";
+ return t;
+ },
+ renderTextAt:function(valign,align, x,y,t,c,w){
+ var text=this.renderText.call(this,x,y,t,c,w);
+ if (text){
+ if (valign){
+ if(valign == "middle")
+ text.style.top = parseInt(y-text.offsetHeight/2,10) + "px";
+ else
+ text.style.top = y-text.offsetHeight + "px";
+ }
+ if (align){
+ if(align == "left")
+ text.style.left = x-text.offsetWidth + "px";
+ else
+ text.style.left = parseInt(x-text.offsetWidth/2,10) + "px";
+ }
+ }
+ return text;
+ },
+ clearCanvas:function(){
+ for(var i=0; i < this._canvas_labels.length;i++)
+ this._obj.removeChild(this._canvas_labels[i]);
+ this._canvas_labels = [];
+ if (this._obj._htmlmap){
+ this._obj._htmlmap.parentNode.removeChild(this._obj._htmlmap);
+ this._obj._htmlmap = null;
+ }
+ //FF breaks, when we are using clear canvas and call clearRect without parameters
+ this.getCanvas().clearRect(0,0,this._canvas.offsetWidth, this._canvas.offsetHeight);
+ }
+};
+
+
+/* DHX INITIAL FILE 'D:\dev\xampp\htdocs\temp\chart\dhtmlxCore/sources//chart.js'*/
+
+
+/*DHX:Depend chart.css*/
+/*DHX:Depend canvas.js*/
+/*DHX:Depend load.js*/
+
+/*DHX:Depend compatibility_grid.js*/
+/*DHX:Depend compatibility_layout.js*/
+
+/*DHX:Depend config.js*/
+/*DHX:Depend destructor.js*/
+/*DHX:Depend mouse.js*/
+/*DHX:Depend key.js*/
+/*DHX:Depend group.js*/
+/*DHX:Depend autotooltip.js*/
+
+/*DHX:Depend ext/chart/chart_base.js*/
+/*DHX:Depend ext/chart/chart_pie.js*/ //+pie3d
+/*DHX:Depend ext/chart/chart_bar.js*/
+/*DHX:Depend ext/chart/chart_line.js*/
+/*DHX:Depend ext/chart/chart_barh.js*/
+/*DHX:Depend ext/chart/chart_stackedbar.js*/
+/*DHX:Depend ext/chart/chart_stackedbarh.js*/
+/*DHX:Depend ext/chart/chart_spline.js*/
+/*DHX:Depend ext/chart/chart_area.js*/ //+stackedArea
+
+/*DHX:Depend math.js*/
+/*DHX:Depend destructor.js*/
+/*DHX:Depend dhtmlx.js*/
+
+
+dhtmlXChart = function(container){
+ this.name = "Chart";
+ this.version = "3.0";
+
+ if (dhtmlx.assert_enabled()) this._assert();
+
+ dhtmlx.extend(this, dhtmlx.Settings);
+
+ this._parseContainer(container,"dhx_chart");
+
+ dhtmlx.extend(this, dhtmlx.DataLoader);
+ this.data.provideApi(this,true);
+
+ dhtmlx.extend(this, dhtmlx.EventSystem);
+ dhtmlx.extend(this, dhtmlx.MouseEvents);
+ dhtmlx.extend(this, dhtmlx.Destruction);
+ dhtmlx.extend(this, dhtmlx.Canvas);
+ dhtmlx.extend(this, dhtmlx.Group);
+ dhtmlx.extend(this, dhtmlx.AutoTooltip);
+
+ for (var key in dhtmlx.chart)
+ dhtmlx.extend(this, dhtmlx.chart[key]);
+
+ this._parseSettings(container,{
+ color:"RAINBOW",
+ alpha:"1",
+ label:false,
+ value:"{obj.value}",
+ padding:{},
+ view:"pie",
+ lineColor:"#ffffff",
+ cant:0.5,
+ width: 15,
+ labelWidth:100,
+ line:{},
+ item:{},
+ shadow:true,
+ gradient:false,
+ border:true,
+ labelOffset: 20,
+ origin:"auto"
+ });
+ this._series = [this._settings];
+ this.data.attachEvent("onStoreUpdated",dhtmlx.bind(function(){
+ this.render();
+ },this));
+ this.attachEvent("onLocateData", this._switchSerie);
+};
+dhtmlXChart.prototype={
+ _id:"dhx_area_id",
+ on_click:{
+ },
+ on_dblclick:{
+ },
+ on_mouse_move:{
+ },
+ resize:function(){
+ this._resizeCanvas();
+ this.render();
+ },
+ view_setter:function(name, val){
+ if (!dhtmlx.chart[val])
+ dhtmlx.error("Chart type extension is not loaded: "+val);
+ //if you will need to add more such settings - move them ( and this one ) in a separate methods
+
+ if (typeof this._settings.offset == "undefined"){
+ if (val == "area" || val == "stackedArea")
+ this._settings.offset = false;
+ else
+ this._settings.offset = true;
+ }
+
+
+ return val;
+ },
+ render:function(){
+ if (!this.callEvent("onBeforeRender",[this.data]))
+ return;
+
+ this.clearCanvas();
+ if(this._settings.legend){
+ this._drawLegend(this.getCanvas(),
+ this.data.getRange(),
+ this._obj.offsetWidth,
+ this._obj.offsetHeight
+ );
+ }
+ var bounds = this._getChartBounds(this._obj.offsetWidth,this._obj.offsetHeight);
+ var map = new dhtmlx.ui.Map(this._id);
+
+ var temp = this._settings;
+ for(var i=0; i < this._series.length;i++){
+ this._settings = this._series[i];
+ this["pvt_render_"+this._settings.view](
+ this.getCanvas(),
+ this.data.getRange(),
+ bounds.start,
+ bounds.end,
+ i,
+ map
+ );
+ }
+ map.render(this._obj);
+ this._settings = temp;
+ },
+
+ value_setter:dhtmlx.Template.obj_setter,
+ alpha_setter:dhtmlx.Template.obj_setter,
+ label_setter:dhtmlx.Template.obj_setter,
+ lineColor_setter:dhtmlx.Template.obj_setter,
+ pieInnerText_setter:dhtmlx.Template.obj_setter,
+ gradient_setter:function(name,config){
+ if((typeof(config)!="function")&&config&&(config === true||config!="3d"))
+ config = "light";
+ return config;
+ },
+ colormap:{
+ "RAINBOW":function(obj){
+ var pos = Math.floor(this.indexById(obj.id)/this.dataCount()*1536);
+ if (pos==1536) pos-=1;
+ return this._rainbow[Math.floor(pos/256)](pos%256);
+ }
+ },
+ color_setter:function(name, value){
+ return this.colormap[value]||dhtmlx.Template.obj_setter(name, value);
+ },
+ legend_setter:function(name, config){
+ if(typeof(config)!="object") //allow to use template string instead of object
+ config={template:config};
+
+ this._mergeSettings(config,{
+ width:150,
+ height:18,
+ layout:"y",
+ align:"left",
+ valign:"bottom",
+ template:"",
+ marker:{
+ type:"square",
+ width:25,
+ height:15
+ }
+ });
+
+ config.template = dhtmlx.Template.setter(0,config.template);
+ return config;
+ },
+ item_setter:function(name, config){
+ if(typeof(config)!="object")
+ config={color:config, borderColor:config};
+
+ this._mergeSettings(config,{
+ radius:4,
+ color:"#000000",
+ borderColor:"#000000",
+ borderWidth:2
+ });
+
+ config.color = dhtmlx.Template.setter(0,config.color);
+ config.borderColor = dhtmlx.Template.setter(0,config.borderColor);
+ return config;
+ },
+ line_setter:function(name, config){
+ if(typeof(config)!="object")
+ config={color:config};
+
+ this._mergeSettings(config,{
+ width:3,
+ color:"#d4d4d4"
+ });
+
+ config.color = dhtmlx.Template.setter(0,config.color);
+ return config;
+ },
+ padding_setter:function(name, config){
+ if(typeof(config)!="object")
+ config={left:config, right:config, top:config, bottom:config};
+ this._mergeSettings(config,{
+ left:50,
+ right:20,
+ top:35,
+ bottom:40
+ });
+ return config;
+ },
+ xAxis_setter:function(name, config){
+ if(!config) return false;
+ if(typeof(config)!="object")
+ config={ template:config };
+
+ this._mergeSettings(config,{
+ title:"",
+ color:"#000000",
+ template:"{obj}",
+ lines:false
+ });
+
+ if(config.template)
+ config.template = dhtmlx.Template.setter(0,config.template);
+ return config;
+ },
+ yAxis_setter:function(name, config){
+ this._mergeSettings(config,{
+ title:"",
+ color:"#000000",
+ template:"{obj}",
+ lines:true
+ });
+
+ if(config.template)
+ config.template = dhtmlx.Template.setter(0,config.template);
+ return config;
+ },
+ _drawScales:function(ctx,data,point0,point1,start,end,cellWidth){
+ var y = this._drawYAxis(ctx,data,point0,point1,start,end);
+ this._drawXAxis(ctx,data,point0,point1,cellWidth,y);
+ return y;
+ },
+ _drawXAxis:function(ctx,data,point0,point1,cellWidth,y){
+ if (!this._settings.xAxis) return;
+
+ var x0 = point0.x-0.5;
+ var y0 = parseInt((y?y:point1.y),10)+0.5;
+
+ var x1 = point1.x;
+ var unit_pos;
+ var center = true;
+
+ this._drawLine(ctx,x0,y0,x1,y0,this._settings.xAxis.color,1);
+
+ for(var i=0; i < data.length;i ++){
+ if(this._settings.offset === true)
+ unit_pos = x0+cellWidth/2+i*cellWidth;
+ else{
+ unit_pos = x0+i*cellWidth;
+ center = !!i;
+ }
+ /*scale labels*/
+ var top = ((this._settings.origin!="auto")&&(this._settings.view=="bar")&&(parseFloat(this._settings.value(data[i]))<this._settings.origin));
+ this._drawXAxisLabel(unit_pos,y0,data[i],center,top);
+ /*draws a vertical line for the horizontal scale*/
+ if(this._settings.view_setter != "bar")
+ this._drawXAxisLine(ctx,unit_pos,point1.y,point0.y);
+ }
+
+ this.renderTextAt(true, false, x0,point1.y+this._settings.padding.bottom-3,
+ this._settings.xAxis.title,
+ "dhx_axis_title_x",
+ point1.x - point0.x
+ );
+
+ /*the right border in lines in scale are enabled*/
+ if (!this._settings.xAxis.lines || !this._settings.offset) return;
+ this._drawLine(ctx,x1+0.5,point1.y,x1+0.5,point0.y+0.5,this._settings.xAxis.color,0.2);
+ },
+ _drawYAxis:function(ctx,data,point0,point1,start,end){
+ var step;
+ var scaleParam= {};
+ if (!this._settings.yAxis) return;
+
+ var x0 = point0.x - 0.5;
+ var y0 = point1.y;
+ var y1 = point0.y;
+ var lineX = point1.y;
+
+ this._drawLine(ctx,x0,y0,x0,y1,this._settings.yAxis.color,1);
+
+ if(this._settings.yAxis.step)
+ step = parseFloat(this._settings.yAxis.step);
+
+ if(typeof this._settings.yAxis.step =="undefined"||typeof this._settings.yAxis.start=="undefined"||typeof this._settings.yAxis.end =="undefined"){
+ scaleParam = this._calculateScale(start,end);
+ start = scaleParam.start;
+ end = scaleParam.end;
+ step = scaleParam.step;
+
+ this._settings.yAxis.end = end;
+ this._settings.yAxis.start = start;
+ }
+
+ if(step===0) return;
+ var stepHeight = (y0-y1)*step/(end-start);
+ var c = 0;
+ for(var i = start; i<=end; i += step){
+ if(scaleParam.fixNum) i = parseFloat((new Number(i)).toFixed(scaleParam.fixNum));
+ var yi = Math.floor(y0-c*stepHeight)+ 0.5;/*canvas line fix*/
+ if(!(i==start&&this._settings.origin=="auto") &&this._settings.yAxis.lines)
+ this._drawLine(ctx,x0,yi,point1.x,yi,this._settings.yAxis.color,0.2);
+ if(i == this._settings.origin) lineX = yi;
+ this.renderText(0,yi-5,
+ this._settings.yAxis.template(i.toString()),
+ "dhx_axis_item_y",
+ point0.x-5
+ );
+ c++;
+ }
+ this._setYAxisTitle(point0,point1);
+ return lineX;
+ },
+ _setYAxisTitle:function(point0,point1){
+ var text=this.renderTextAt("middle",false,0,parseInt((point1.y-point0.y)/2+point0.y,10),this._settings.yAxis.title,"dhx_axis_title_y");
+ if (text)
+ text.style.left = (dhtmlx.env.transform?(text.offsetHeight-text.offsetWidth)/2:0)+"px";
+ },
+ _calculateScale:function(nmin,nmax){
+ var step,start,end;
+ step = ((nmax-nmin)/8)||1;
+ var power = Math.floor(this._log10(step));
+ var calculStep = Math.pow(10,power);
+ var stepVal = step/calculStep;
+ stepVal = (stepVal>5?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) };
+ },
+ _getLimits:function(orientation){
+ var maxValue,minValue;
+ var axis = ((arguments.length && orientation=="h")?this._settings.xAxis:this._settings.yAxis);
+ if(axis&&(typeof axis.end!="undefied")&&(typeof axis.start!="undefied")&&axis.step){
+ maxValue = parseFloat(axis.end);
+ minValue = parseFloat(axis.start);
+ }
+ else{
+ maxValue = this.max(this._series[0].value);
+ minValue = this.min(this._series[0].value);
+ if(this._series.length>1)
+ for(var i=1; i < this._series.length;i++){
+ var maxI = this.max(this._series[i].value);
+ var minI = this.min(this._series[i].value);
+ if (maxI > maxValue) maxValue = maxI;
+ if (minI < minValue) minValue = minI;
+ }
+ }
+ return {max:maxValue,min:minValue};
+ },
+ _log10:function(n){
+ var method_name="log";
+ return Math.floor((Math[method_name](n)/Math.LN10));
+ },
+ _drawXAxisLabel:function(x,y,obj,center,top){
+ if (!this._settings.xAxis) return;
+ var elem = this.renderTextAt(top, center, x,y,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";}
+ ],
+ /**
+ * adds series to the chart (value and color properties)
+ * @param: obj - obj with configuration properties
+ */
+ addSeries:function(obj){
+ var temp = this._settings; this._settings = dhtmlx.extend({},temp);
+ this._parseSettings(obj,{});
+ this._series.push(this._settings);
+ this._settings = temp;
+ },
+ /*switch global settings to serit in question*/
+ _switchSerie:function(id, tag){
+ this._active_serie = tag.getAttribute("userdata");
+ for (var i=0; i < this._series.length; i++) {
+ var tip = this._series[i].tooltip;
+ if (tip)
+ tip.disable();
+ }
+ var tip = this._series[this._active_serie].tooltip;
+ if (tip)
+ tip.enable();
+ },
+ /**
+ * renders legend block
+ * @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
+ */
+ _drawLegend:function(ctx,data,width,height){
+ /*position of the legend block*/
+ var x=0,y=0;
+ /*legend config*/
+ var legend = this._settings.legend;
+ /*the legend sizes*/
+ var legendHeight,legendWidth;
+
+ var style = (this._settings.legend.layout!="x"?"width:"+legend.width+"px":"");
+ /*creation of legend container*/
+ var legendContainer = dhtmlx.html.create("DIV",{
+ "class":"dhx_chart_legend",
+ "style":"left:"+x+"px; top:"+y+"px;"+style
+ },"");
+ this._obj.appendChild(legendContainer);
+ /*rendering legend text items*/
+ var legendItems = [];
+ if(!legend.values)
+ for(var i = 0; i < data.length; i++){
+ legendItems.push(this._drawLegendText(legendContainer,legend.template(data[i])));
+ }
+ else
+ for(var i = 0; i < legend.values.length; i++){
+ legendItems.push(this._drawLegendText(legendContainer,legend.values[i].text));
+ }
+ legendWidth = legendContainer.offsetWidth;
+ legendHeight = legendContainer.offsetHeight;
+ this._settings.legend.width = legendWidth;
+ this._settings.legend.height = legendHeight;
+ /*setting legend position*/
+ if(legendWidth<this._obj.offsetWidth){
+ if(legend.layout == "x"&&legend.align == "center")
+ x = (this._obj.offsetWidth-legendWidth)/2;
+ if(legend.align == "right"){
+ x = this._obj.offsetWidth-legendWidth;
+ }
+ }
+
+ if(legendHeight<this._obj.offsetHeight){
+ if(legend.valign == "middle"&&legend.align != "center"&&legend.layout != "x")
+ y = (this._obj.offsetHeight-legendHeight)/2;
+ else if(legend.valign == "bottom")
+ y = this._obj.offsetHeight-legendHeight;
+ }
+ legendContainer.style.left = x+"px";
+ legendContainer.style.top = y+"px";
+
+ /*drawing colorful markers*/
+ for(var i = 0; i < legendItems.length; i++){
+ var item = legendItems[i];
+ var itemColor = (legend.values?legend.values[i].color:this._settings.color.call(this,data[i]));
+ this._drawLegendMarker(ctx,item.offsetLeft+x,item.offsetTop+y,itemColor);
+ }
+ legendItems = null;
+ },
+ /**
+ * appends legend item to legend block
+ * @param: ctx - canvas object
+ * @param: obj - data object that needs being represented
+ */
+ _drawLegendText:function(cont,value){
+ var style = "";
+ if(this._settings.legend.layout=="x")
+ style = "float:left;";
+ /*the text of the legend item*/
+ var text = dhtmlx.html.create("DIV",{
+ "style":style+"padding-left:"+(10+this._settings.legend.marker.width)+"px",
+ "class":"dhx_chart_legend_item"
+ },value);
+ cont.appendChild(text);
+ return text;
+ },
+ /**
+ * draw legend colorful marder
+ * @param: ctx - canvas object
+ * @param: x - the horizontal position of the marker
+ * @param: y - the vertical position of the marker
+ * @param: obj - data object which color needs being used
+ */
+ _drawLegendMarker:function(ctx,x,y,color){
+ var details = this._settings.legend;
+
+ ctx.strokeStyle = ctx.fillStyle = color;
+ ctx.lineWidth = details.marker.height;
+ ctx.lineCap = details.marker.type;
+ ctx.beginPath();
+ /*start of marker*/
+ x += ctx.lineWidth/2+5;
+ y += ctx.lineWidth/2+3;
+ ctx.moveTo(x,y);
+ var x1 = x + details.marker.width-details.marker.height +1;
+ ctx.lineTo(x1,y);
+ ctx.stroke();
+ },
+ /**
+ * gets the points those represent chart left top and right bottom bounds
+ * @param: width - the width of the chart container
+ * @param: height - the height of the chart container
+ */
+ _getChartBounds:function(width,height){
+ var chartX0, chartY0, chartX1, chartY1;
+
+ chartX0 = this._settings.padding.left;
+ chartY0 = this._settings.padding.top;
+ chartX1 = width - this._settings.padding.right;
+ chartY1 = height - this._settings.padding.bottom;
+
+ if(this._settings.legend){
+ var legend = this._settings.legend;
+ /*legend size*/
+ var legendWidth = this._settings.legend.width;
+ var legendHeight = this._settings.legend.height;
+
+ /*if legend is horizontal*/
+ if(legend.layout == "x"){
+ if(legend.valign == "center"){
+ if(legend.align == "right")
+ chartX1 -= legendWidth;
+ else if(legend.align == "left")
+ chartX0 += legendWidth;
+ }
+ else if(legend.valign == "bottom"){
+ chartY1 -= legendHeight;
+ }
+ else{
+ chartY0 += legendHeight;
+ }
+ }
+ /*vertical scale*/
+ else{
+ if(legend.align == "right")
+ chartX1 -= legendWidth;
+ else if(legend.align == "left")
+ chartX0 += legendWidth;
+ }
+ }
+ return {start:{x:chartX0,y:chartY0},end:{x:chartX1,y:chartY1}};
+ },
+ /**
+ * gets the maximum and minimum values for the stacked chart
+ * @param: data - data set
+ */
+ _getStackedLimits:function(data){
+ var maxValue,minValue;
+ if(this._settings.yAxis&&(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{
+ for(var i=0; i < data.length; i++){
+ data[i].$sum = 0 ;
+ data[i].$min = Infinity;
+ for(var j =0; j < this._series.length;j++){
+ var value = parseFloat(this._series[j].value(data[i]));
+ if(isNaN(value)) continue;
+ data[i].$sum += value;
+ if(value < data[i].$min) data[i].$min = value;
+ }
+ }
+ maxValue = -Infinity;
+ minValue = Infinity;
+ for(var i=0; i < data.length; i++){
+ if (data[i].$sum > maxValue) maxValue = data[i].$sum ;
+ if (data[i].$min < minValue) minValue = data[i].$min ;
+ }
+ if(minValue>0) minValue =0;
+ }
+ return {max:maxValue,min:minValue};
+ },
+ /*adds colors to the gradient object*/
+ _setBarGradient:function(ctx,x1,y1,x2,y2,type,color,axis){
+ var gradient,offset;
+ if(type == "light"){
+ if(axis == "x")
+ gradient = ctx.createLinearGradient(x1,y1,x2,y1);
+ else
+ gradient = ctx.createLinearGradient(x1,y1,x1,y2);
+ gradient.addColorStop(0,"#FFFFFF");
+ gradient.addColorStop(0.9,color);
+ gradient.addColorStop(1,color);
+ offset = 2;
+ }
+ else{
+ ctx.globalAlpha = 0.37;
+ offset = 0;
+ if(axis == "x")
+ gradient = ctx.createLinearGradient(x1,y2,x1,y1);
+ else
+ gradient = ctx.createLinearGradient(x1,y1,x2,y1);
+ gradient.addColorStop(0,"#000000");
+ gradient.addColorStop(0.5,"#FFFFFF");
+ gradient.addColorStop(0.6,"#FFFFFF");
+ gradient.addColorStop(1,"#000000");
+ }
+ return {gradient:gradient,offset:offset};
+ }
+};
+
+dhtmlx.compat("layout"); \ No newline at end of file
diff --git a/addons/base_graph/static/lib/dhtmlxGraph/codebase/thirdparty/excanvas/AUTHORS b/addons/base_graph/static/lib/dhtmlxGraph/codebase/thirdparty/excanvas/AUTHORS
new file mode 100644
index 00000000000..90decb3077e
--- /dev/null
+++ b/addons/base_graph/static/lib/dhtmlxGraph/codebase/thirdparty/excanvas/AUTHORS
@@ -0,0 +1,10 @@
+ExplorerCanvas
+
+Google Open Source:
+ <http://code.google.com>
+ <opensource@google.com>
+
+Developers:
+ Emil A Eklund <emil@eae.net>
+ Erik Arvidsson <erik@eae.net>
+ Glen Murphy <glen@glenmurphy.com> \ No newline at end of file
diff --git a/addons/base_graph/static/lib/dhtmlxGraph/codebase/thirdparty/excanvas/COPYING b/addons/base_graph/static/lib/dhtmlxGraph/codebase/thirdparty/excanvas/COPYING
new file mode 100644
index 00000000000..d6456956733
--- /dev/null
+++ b/addons/base_graph/static/lib/dhtmlxGraph/codebase/thirdparty/excanvas/COPYING
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/addons/base_graph/static/lib/dhtmlxGraph/codebase/thirdparty/excanvas/README b/addons/base_graph/static/lib/dhtmlxGraph/codebase/thirdparty/excanvas/README
new file mode 100644
index 00000000000..eb7c42f40be
--- /dev/null
+++ b/addons/base_graph/static/lib/dhtmlxGraph/codebase/thirdparty/excanvas/README
@@ -0,0 +1,22 @@
+ExplorerCanvas
+Copyright 2006 Google Inc.
+
+-------------------------------------------------------------------------------
+DESCRIPTION
+
+Firefox, Safari and Opera 9 support the canvas tag to allow 2D command-based
+drawing operations. ExplorerCanvas brings the same functionality to Internet
+Explorer; web developers only need to include a single script tag in their
+existing canvas webpages to enable this support.
+
+
+-------------------------------------------------------------------------------
+INSTALLATION
+
+Include the ExplorerCanvas tag in the same directory as your HTML files, and
+add the following code to your page, preferably in the <head> tag.
+
+<!--[if IE]><script type="text/javascript" src="excanvas.js"></script><![endif]-->
+
+If you run into trouble, please look at the included example code to see how
+to best implement this \ No newline at end of file
diff --git a/addons/base_graph/static/lib/dhtmlxGraph/codebase/thirdparty/excanvas/excanvas.js b/addons/base_graph/static/lib/dhtmlxGraph/codebase/thirdparty/excanvas/excanvas.js
new file mode 100644
index 00000000000..3fe46d3336f
--- /dev/null
+++ b/addons/base_graph/static/lib/dhtmlxGraph/codebase/thirdparty/excanvas/excanvas.js
@@ -0,0 +1,927 @@
+// Copyright 2006 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+// Known Issues:
+//
+// * Patterns are not implemented.
+// * Radial gradient are not implemented. The VML version of these look very
+// different from the canvas one.
+// * Clipping paths are not implemented.
+// * Coordsize. The width and height attribute have higher priority than the
+// width and height style values which isn't correct.
+// * Painting mode isn't implemented.
+// * Canvas width/height should is using content-box by default. IE in
+// Quirks mode will draw the canvas using border-box. Either change your
+// doctype to HTML5
+// (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)
+// or use Box Sizing Behavior from WebFX
+// (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
+// * Non uniform scaling does not correctly scale strokes.
+// * Optimize. There is always room for speed improvements.
+
+// Only add this code if we do not already have a canvas implementation
+if (!document.createElement('canvas').getContext) {
+
+(function() {
+
+ // alias some functions to make (compiled) code shorter
+ var m = Math;
+ var mr = m.round;
+ var ms = m.sin;
+ var mc = m.cos;
+ var abs = m.abs;
+ var sqrt = m.sqrt;
+
+ // this is used for sub pixel precision
+ var Z = 10;
+ var Z2 = Z / 2;
+
+ /**
+ * This funtion is assigned to the <canvas> elements as element.getContext().
+ * @this {HTMLElement}
+ * @return {CanvasRenderingContext2D_}
+ */
+ function getContext() {
+ return this.context_ ||
+ (this.context_ = new CanvasRenderingContext2D_(this));
+ }
+
+ var slice = Array.prototype.slice;
+
+ /**
+ * Binds a function to an object. The returned function will always use the
+ * passed in {@code obj} as {@code this}.
+ *
+ * Example:
+ *
+ * g = bind(f, obj, a, b)
+ * g(c, d) // will do f.call(obj, a, b, c, d)
+ *
+ * @param {Function} f The function to bind the object to
+ * @param {Object} obj The object that should act as this when the function
+ * is called
+ * @param {*} var_args Rest arguments that will be used as the initial
+ * arguments when the function is called
+ * @return {Function} A new function that has bound this
+ */
+ function bind(f, obj, var_args) {
+ var a = slice.call(arguments, 2);
+ return function() {
+ return f.apply(obj, a.concat(slice.call(arguments)));
+ };
+ }
+
+ var G_vmlCanvasManager_ = {
+ init: function(opt_doc) {
+ if (/MSIE/.test(navigator.userAgent) && !window.opera) {
+ var doc = opt_doc || document;
+ // Create a dummy element so that IE will allow canvas elements to be
+ // recognized.
+ doc.createElement('canvas');
+ doc.attachEvent('onreadystatechange', bind(this.init_, this, doc));
+ }
+ },
+
+ init_: function(doc) {
+ // create xmlns
+ if (!doc.namespaces['g_vml_']) {
+ doc.namespaces.add('g_vml_', 'urn:schemas-microsoft-com:vml',
+ '#default#VML');
+
+ }
+ if (!doc.namespaces['g_o_']) {
+ doc.namespaces.add('g_o_', 'urn:schemas-microsoft-com:office:office',
+ '#default#VML');
+ }
+
+ // Setup default CSS. Only add one style sheet per document
+ if (!doc.styleSheets['ex_canvas_']) {
+ var ss = doc.createStyleSheet();
+ ss.owningElement.id = 'ex_canvas_';
+ ss.cssText = 'canvas{display:inline-block;overflow:hidden;' +
+ // default size is 300x150 in Gecko and Opera
+ 'text-align:left;width:300px;height:150px}' +
+ 'g_vml_\\:*{behavior:url(#default#VML)}' +
+ 'g_o_\\:*{behavior:url(#default#VML)}';
+
+ }
+
+ // find all canvas elements
+ var els = doc.getElementsByTagName('canvas');
+ for (var i = 0; i < els.length; i++) {
+ this.initElement(els[i]);
+ }
+ },
+
+ /**
+ * Public initializes a canvas element so that it can be used as canvas
+ * element from now on. This is called automatically before the page is
+ * loaded but if you are creating elements using createElement you need to
+ * make sure this is called on the element.
+ * @param {HTMLElement} el The canvas element to initialize.
+ * @return {HTMLElement} the element that was created.
+ */
+ initElement: function(el) {
+ if (!el.getContext) {
+
+ el.getContext = getContext;
+
+ // Remove fallback content. There is no way to hide text nodes so we
+ // just remove all childNodes. We could hide all elements and remove
+ // text nodes but who really cares about the fallback content.
+ el.innerHTML = '';
+
+ // do not use inline function because that will leak memory
+ el.attachEvent('onpropertychange', onPropertyChange);
+ el.attachEvent('onresize', onResize);
+
+ var attrs = el.attributes;
+ if (attrs.width && attrs.width.specified) {
+ // TODO: use runtimeStyle and coordsize
+ // el.getContext().setWidth_(attrs.width.nodeValue);
+ el.style.width = attrs.width.nodeValue + 'px';
+ } else {
+ el.width = el.clientWidth;
+ }
+ if (attrs.height && attrs.height.specified) {
+ // TODO: use runtimeStyle and coordsize
+ // el.getContext().setHeight_(attrs.height.nodeValue);
+ el.style.height = attrs.height.nodeValue + 'px';
+ } else {
+ el.height = el.clientHeight;
+ }
+ //el.getContext().setCoordsize_()
+ }
+ return el;
+ }
+ };
+
+ function onPropertyChange(e) {
+ var el = e.srcElement;
+
+ switch (e.propertyName) {
+ case 'width':
+ el.style.width = el.attributes.width.nodeValue + 'px';
+ el.getContext().clearRect();
+ break;
+ case 'height':
+ el.style.height = el.attributes.height.nodeValue + 'px';
+ el.getContext().clearRect();
+ break;
+ }
+ }
+
+ function onResize(e) {
+ var el = e.srcElement;
+ if (el.firstChild) {
+ el.firstChild.style.width = el.clientWidth + 'px';
+ el.firstChild.style.height = el.clientHeight + 'px';
+ }
+ }
+
+ G_vmlCanvasManager_.init();
+
+ // precompute "00" to "FF"
+ var dec2hex = [];
+ for (var i = 0; i < 16; i++) {
+ for (var j = 0; j < 16; j++) {
+ dec2hex[i * 16 + j] = i.toString(16) + j.toString(16);
+ }
+ }
+
+ function createMatrixIdentity() {
+ return [
+ [1, 0, 0],
+ [0, 1, 0],
+ [0, 0, 1]
+ ];
+ }
+
+ function matrixMultiply(m1, m2) {
+ var result = createMatrixIdentity();
+
+ for (var x = 0; x < 3; x++) {
+ for (var y = 0; y < 3; y++) {
+ var sum = 0;
+
+ for (var z = 0; z < 3; z++) {
+ sum += m1[x][z] * m2[z][y];
+ }
+
+ result[x][y] = sum;
+ }
+ }
+ return result;
+ }
+
+ function copyState(o1, o2) {
+ o2.fillStyle = o1.fillStyle;
+ o2.lineCap = o1.lineCap;
+ o2.lineJoin = o1.lineJoin;
+ o2.lineWidth = o1.lineWidth;
+ o2.miterLimit = o1.miterLimit;
+ o2.shadowBlur = o1.shadowBlur;
+ o2.shadowColor = o1.shadowColor;
+ o2.shadowOffsetX = o1.shadowOffsetX;
+ o2.shadowOffsetY = o1.shadowOffsetY;
+ o2.strokeStyle = o1.strokeStyle;
+ o2.globalAlpha = o1.globalAlpha;
+ o2.arcScaleX_ = o1.arcScaleX_;
+ o2.arcScaleY_ = o1.arcScaleY_;
+ o2.lineScale_ = o1.lineScale_;
+ }
+
+ function processStyle(styleString) {
+ var str, alpha = 1;
+
+ styleString = String(styleString);
+ if (styleString.substring(0, 3) == 'rgb') {
+ var start = styleString.indexOf('(', 3);
+ var end = styleString.indexOf(')', start + 1);
+ var guts = styleString.substring(start + 1, end).split(',');
+
+ str = '#';
+ for (var i = 0; i < 3; i++) {
+ str += dec2hex[Number(guts[i])];
+ }
+
+ if (guts.length == 4 && styleString.substr(3, 1) == 'a') {
+ alpha = guts[3];
+ }
+ } else {
+ str = styleString;
+ }
+
+ return {color: str, alpha: alpha};
+ }
+
+ function processLineCap(lineCap) {
+ switch (lineCap) {
+ case 'butt':
+ return 'flat';
+ case 'round':
+ return 'round';
+ case 'square':
+ default:
+ return 'square';
+ }
+ }
+
+ /**
+ * This class implements CanvasRenderingContext2D interface as described by
+ * the WHATWG.
+ * @param {HTMLElement} surfaceElement The element that the 2D context should
+ * be associated with
+ */
+ function CanvasRenderingContext2D_(surfaceElement) {
+ this.m_ = createMatrixIdentity();
+
+ this.mStack_ = [];
+ this.aStack_ = [];
+ this.currentPath_ = [];
+
+ // Canvas context properties
+ this.strokeStyle = '#000';
+ this.fillStyle = '#000';
+
+ this.lineWidth = 1;
+ this.lineJoin = 'miter';
+ this.lineCap = 'butt';
+ this.miterLimit = Z * 1;
+ this.globalAlpha = 1;
+ this.canvas = surfaceElement;
+
+ var el = surfaceElement.ownerDocument.createElement('div');
+ el.style.width = surfaceElement.clientWidth + 'px';
+ el.style.height = surfaceElement.clientHeight + 'px';
+ el.style.overflow = 'hidden';
+ el.style.position = 'absolute';
+ surfaceElement.appendChild(el);
+
+ this.element_ = el;
+ this.arcScaleX_ = 1;
+ this.arcScaleY_ = 1;
+ this.lineScale_ = 1;
+ }
+
+ var contextPrototype = CanvasRenderingContext2D_.prototype;
+ contextPrototype.clearRect = function() {
+ this.element_.innerHTML = '';
+ };
+
+ contextPrototype.beginPath = function() {
+ // TODO: Branch current matrix so that save/restore has no effect
+ // as per safari docs.
+ this.currentPath_ = [];
+ };
+
+ contextPrototype.moveTo = function(aX, aY) {
+ var p = this.getCoords_(aX, aY);
+ this.currentPath_.push({type: 'moveTo', x: p.x, y: p.y});
+ this.currentX_ = p.x;
+ this.currentY_ = p.y;
+ };
+
+ contextPrototype.lineTo = function(aX, aY) {
+ var p = this.getCoords_(aX, aY);
+ this.currentPath_.push({type: 'lineTo', x: p.x, y: p.y});
+
+ this.currentX_ = p.x;
+ this.currentY_ = p.y;
+ };
+
+ contextPrototype.bezierCurveTo = function(aCP1x, aCP1y,
+ aCP2x, aCP2y,
+ aX, aY) {
+ var p = this.getCoords_(aX, aY);
+ var cp1 = this.getCoords_(aCP1x, aCP1y);
+ var cp2 = this.getCoords_(aCP2x, aCP2y);
+ bezierCurveTo(this, cp1, cp2, p);
+ };
+
+ // Helper function that takes the already fixed cordinates.
+ function bezierCurveTo(self, cp1, cp2, p) {
+ self.currentPath_.push({
+ type: 'bezierCurveTo',
+ cp1x: cp1.x,
+ cp1y: cp1.y,
+ cp2x: cp2.x,
+ cp2y: cp2.y,
+ x: p.x,
+ y: p.y
+ });
+ self.currentX_ = p.x;
+ self.currentY_ = p.y;
+ }
+
+ contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {
+ // the following is lifted almost directly from
+ // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes
+
+ var cp = this.getCoords_(aCPx, aCPy);
+ var p = this.getCoords_(aX, aY);
+
+ var cp1 = {
+ x: this.currentX_ + 2.0 / 3.0 * (cp.x - this.currentX_),
+ y: this.currentY_ + 2.0 / 3.0 * (cp.y - this.currentY_)
+ };
+ var cp2 = {
+ x: cp1.x + (p.x - this.currentX_) / 3.0,
+ y: cp1.y + (p.y - this.currentY_) / 3.0
+ };
+
+ bezierCurveTo(this, cp1, cp2, p);
+ };
+
+ contextPrototype.arc = function(aX, aY, aRadius,
+ aStartAngle, aEndAngle, aClockwise) {
+ aRadius *= Z;
+ var arcType = aClockwise ? 'at' : 'wa';
+
+ var xStart = aX + mc(aStartAngle) * aRadius - Z2;
+ var yStart = aY + ms(aStartAngle) * aRadius - Z2;
+
+ var xEnd = aX + mc(aEndAngle) * aRadius - Z2;
+ var yEnd = aY + ms(aEndAngle) * aRadius - Z2;
+
+ // IE won't render arches drawn counter clockwise if xStart == xEnd.
+ if (xStart == xEnd && !aClockwise) {
+ xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something
+ // that can be represented in binary
+ }
+
+ var p = this.getCoords_(aX, aY);
+ var pStart = this.getCoords_(xStart, yStart);
+ var pEnd = this.getCoords_(xEnd, yEnd);
+
+ this.currentPath_.push({type: arcType,
+ x: p.x,
+ y: p.y,
+ radius: aRadius,
+ xStart: pStart.x,
+ yStart: pStart.y,
+ xEnd: pEnd.x,
+ yEnd: pEnd.y});
+
+ };
+
+ contextPrototype.rect = function(aX, aY, aWidth, aHeight) {
+ this.moveTo(aX, aY);
+ this.lineTo(aX + aWidth, aY);
+ this.lineTo(aX + aWidth, aY + aHeight);
+ this.lineTo(aX, aY + aHeight);
+ this.closePath();
+ };
+
+ contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) {
+ var oldPath = this.currentPath_;
+ this.beginPath();
+
+ this.moveTo(aX, aY);
+ this.lineTo(aX + aWidth, aY);
+ this.lineTo(aX + aWidth, aY + aHeight);
+ this.lineTo(aX, aY + aHeight);
+ this.closePath();
+ this.stroke();
+
+ this.currentPath_ = oldPath;
+ };
+
+ contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) {
+ var oldPath = this.currentPath_;
+ this.beginPath();
+
+ this.moveTo(aX, aY);
+ this.lineTo(aX + aWidth, aY);
+ this.lineTo(aX + aWidth, aY + aHeight);
+ this.lineTo(aX, aY + aHeight);
+ this.closePath();
+ this.fill();
+
+ this.currentPath_ = oldPath;
+ };
+
+ contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) {
+ var gradient = new CanvasGradient_('gradient');
+ gradient.x0_ = aX0;
+ gradient.y0_ = aY0;
+ gradient.x1_ = aX1;
+ gradient.y1_ = aY1;
+ return gradient;
+ };
+
+ contextPrototype.createRadialGradient = function(aX0, aY0, aR0,
+ aX1, aY1, aR1) {
+ var gradient = new CanvasGradient_('gradientradial');
+ gradient.x0_ = aX0;
+ gradient.y0_ = aY0;
+ gradient.r0_ = aR0;
+ gradient.x1_ = aX1;
+ gradient.y1_ = aY1;
+ gradient.r1_ = aR1;
+ return gradient;
+ };
+
+ contextPrototype.drawImage = function(image, var_args) {
+ var dx, dy, dw, dh, sx, sy, sw, sh;
+
+ // to find the original width we overide the width and height
+ var oldRuntimeWidth = image.runtimeStyle.width;
+ var oldRuntimeHeight = image.runtimeStyle.height;
+ image.runtimeStyle.width = 'auto';
+ image.runtimeStyle.height = 'auto';
+
+ // get the original size
+ var w = image.width;
+ var h = image.height;
+
+ // and remove overides
+ image.runtimeStyle.width = oldRuntimeWidth;
+ image.runtimeStyle.height = oldRuntimeHeight;
+
+ if (arguments.length == 3) {
+ dx = arguments[1];
+ dy = arguments[2];
+ sx = sy = 0;
+ sw = dw = w;
+ sh = dh = h;
+ } else if (arguments.length == 5) {
+ dx = arguments[1];
+ dy = arguments[2];
+ dw = arguments[3];
+ dh = arguments[4];
+ sx = sy = 0;
+ sw = w;
+ sh = h;
+ } else if (arguments.length == 9) {
+ sx = arguments[1];
+ sy = arguments[2];
+ sw = arguments[3];
+ sh = arguments[4];
+ dx = arguments[5];
+ dy = arguments[6];
+ dw = arguments[7];
+ dh = arguments[8];
+ } else {
+ throw Error('Invalid number of arguments');
+ }
+
+ var d = this.getCoords_(dx, dy);
+
+ var w2 = sw / 2;
+ var h2 = sh / 2;
+
+ var vmlStr = [];
+
+ var W = 10;
+ var H = 10;
+
+ // For some reason that I've now forgotten, using divs didn't work
+ vmlStr.push(' <g_vml_:group',
+ ' coordsize="', Z * W, ',', Z * H, '"',
+ ' coordorigin="0,0"' ,
+ ' style="width:', W, 'px;height:', H, 'px;position:absolute;');
+
+ // If filters are necessary (rotation exists), create them
+ // filters are bog-slow, so only create them if abbsolutely necessary
+ // The following check doesn't account for skews (which don't exist
+ // in the canvas spec (yet) anyway.
+
+ if (this.m_[0][0] != 1 || this.m_[0][1]) {
+ var filter = [];
+
+ // Note the 12/21 reversal
+ filter.push('M11=', this.m_[0][0], ',',
+ 'M12=', this.m_[1][0], ',',
+ 'M21=', this.m_[0][1], ',',
+ 'M22=', this.m_[1][1], ',',
+ 'Dx=', mr(d.x / Z), ',',
+ 'Dy=', mr(d.y / Z), '');
+
+ // Bounding box calculation (need to minimize displayed area so that
+ // filters don't waste time on unused pixels.
+ var max = d;
+ var c2 = this.getCoords_(dx + dw, dy);
+ var c3 = this.getCoords_(dx, dy + dh);
+ var c4 = this.getCoords_(dx + dw, dy + dh);
+
+ max.x = m.max(max.x, c2.x, c3.x, c4.x);
+ max.y = m.max(max.y, c2.y, c3.y, c4.y);
+
+ vmlStr.push('padding:0 ', mr(max.x / Z), 'px ', mr(max.y / Z),
+ 'px 0;filter:progid:DXImageTransform.Microsoft.Matrix(',
+ filter.join(''), ", sizingmethod='clip');")
+ } else {
+ vmlStr.push('top:', mr(d.y / Z), 'px;left:', mr(d.x / Z), 'px;');
+ }
+
+ vmlStr.push(' ">' ,
+ '<g_vml_:image src="', image.src, '"',
+ ' style="width:', Z * dw, 'px;',
+ ' height:', Z * dh, 'px;"',
+ ' cropleft="', sx / w, '"',
+ ' croptop="', sy / h, '"',
+ ' cropright="', (w - sx - sw) / w, '"',
+ ' cropbottom="', (h - sy - sh) / h, '"',
+ ' />',
+ '</g_vml_:group>');
+
+ this.element_.insertAdjacentHTML('BeforeEnd',
+ vmlStr.join(''));
+ };
+
+ contextPrototype.stroke = function(aFill) {
+ var lineStr = [];
+ var lineOpen = false;
+ var a = processStyle(aFill ? this.fillStyle : this.strokeStyle);
+ var color = a.color;
+ var opacity = a.alpha * this.globalAlpha;
+
+ var W = 10;
+ var H = 10;
+
+ lineStr.push('<g_vml_:shape',
+ ' filled="', !!aFill, '"',
+ ' style="position:absolute;width:', W, 'px;height:', H, 'px;"',
+ ' coordorigin="0 0" coordsize="', Z * W, ' ', Z * H, '"',
+ ' stroked="', !aFill, '"',
+ ' path="');
+
+ var newSeq = false;
+ var min = {x: null, y: null};
+ var max = {x: null, y: null};
+
+ for (var i = 0; i < this.currentPath_.length; i++) {
+ var p = this.currentPath_[i];
+ var c;
+
+ switch (p.type) {
+ case 'moveTo':
+ c = p;
+ lineStr.push(' m ', mr(p.x), ',', mr(p.y));
+ break;
+ case 'lineTo':
+ lineStr.push(' l ', mr(p.x), ',', mr(p.y));
+ break;
+ case 'close':
+ lineStr.push(' x ');
+ p = null;
+ break;
+ case 'bezierCurveTo':
+ lineStr.push(' c ',
+ mr(p.cp1x), ',', mr(p.cp1y), ',',
+ mr(p.cp2x), ',', mr(p.cp2y), ',',
+ mr(p.x), ',', mr(p.y));
+ break;
+ case 'at':
+ case 'wa':
+ lineStr.push(' ', p.type, ' ',
+ mr(p.x - this.arcScaleX_ * p.radius), ',',
+ mr(p.y - this.arcScaleY_ * p.radius), ' ',
+ mr(p.x + this.arcScaleX_ * p.radius), ',',
+ mr(p.y + this.arcScaleY_ * p.radius), ' ',
+ mr(p.xStart), ',', mr(p.yStart), ' ',
+ mr(p.xEnd), ',', mr(p.yEnd));
+ break;
+ }
+
+
+ // TODO: Following is broken for curves due to
+ // move to proper paths.
+
+ // Figure out dimensions so we can do gradient fills
+ // properly
+ if (p) {
+ if (min.x == null || p.x < min.x) {
+ min.x = p.x;
+ }
+ if (max.x == null || p.x > max.x) {
+ max.x = p.x;
+ }
+ if (min.y == null || p.y < min.y) {
+ min.y = p.y;
+ }
+ if (max.y == null || p.y > max.y) {
+ max.y = p.y;
+ }
+ }
+ }
+ lineStr.push(' ">');
+
+ if (!aFill) {
+ var lineWidth = this.lineScale_ * this.lineWidth;
+
+ // VML cannot correctly render a line if the width is less than 1px.
+ // In that case, we dilute the color to make the line look thinner.
+ if (lineWidth < 1) {
+ opacity *= lineWidth;
+ }
+
+ lineStr.push(
+ '<g_vml_:stroke',
+ ' opacity="', opacity, '"',
+ ' joinstyle="', this.lineJoin, '"',
+ ' miterlimit="', this.miterLimit, '"',
+ ' endcap="', processLineCap(this.lineCap), '"',
+ ' weight="', lineWidth, 'px"',
+ ' color="', color, '" />'
+ );
+ } else if (typeof this.fillStyle == 'object') {
+ var fillStyle = this.fillStyle;
+ var angle = 0;
+ var focus = {x: 0, y: 0};
+
+ // additional offset
+ var shift = 0;
+ // scale factor for offset
+ var expansion = 1;
+
+ if (fillStyle.type_ == 'gradient') {
+ var x0 = fillStyle.x0_ / this.arcScaleX_;
+ var y0 = fillStyle.y0_ / this.arcScaleY_;
+ var x1 = fillStyle.x1_ / this.arcScaleX_;
+ var y1 = fillStyle.y1_ / this.arcScaleY_;
+ var p0 = this.getCoords_(x0, y0);
+ var p1 = this.getCoords_(x1, y1);
+ var dx = p1.x - p0.x;
+ var dy = p1.y - p0.y;
+ angle = Math.atan2(dx, dy) * 180 / Math.PI;
+
+ // The angle should be a non-negative number.
+ if (angle < 0) {
+ angle += 360;
+ }
+
+ // Very small angles produce an unexpected result because they are
+ // converted to a scientific notation string.
+ if (angle < 1e-6) {
+ angle = 0;
+ }
+ } else {
+ var p0 = this.getCoords_(fillStyle.x0_, fillStyle.y0_);
+ var width = max.x - min.x;
+ var height = max.y - min.y;
+ focus = {
+ x: (p0.x - min.x) / width,
+ y: (p0.y - min.y) / height
+ };
+
+ width /= this.arcScaleX_ * Z;
+ height /= this.arcScaleY_ * Z;
+ var dimension = m.max(width, height);
+ shift = 2 * fillStyle.r0_ / dimension;
+ expansion = 2 * fillStyle.r1_ / dimension - shift;
+ }
+
+ // We need to sort the color stops in ascending order by offset,
+ // otherwise IE won't interpret it correctly.
+ var stops = fillStyle.colors_;
+ stops.sort(function(cs1, cs2) {
+ return cs1.offset - cs2.offset;
+ });
+
+ var length = stops.length;
+ var color1 = stops[0].color;
+ var color2 = stops[length - 1].color;
+ var opacity1 = stops[0].alpha * this.globalAlpha;
+ var opacity2 = stops[length - 1].alpha * this.globalAlpha;
+
+ var colors = [];
+ for (var i = 0; i < length; i++) {
+ var stop = stops[i];
+ colors.push(stop.offset * expansion + shift + ' ' + stop.color);
+ }
+
+ // When colors attribute is used, the meanings of opacity and o:opacity2
+ // are reversed.
+ lineStr.push('<g_vml_:fill type="', fillStyle.type_, '"',
+ ' method="none" focus="100%"',
+ ' color="', color1, '"',
+ ' color2="', color2, '"',
+ ' colors="', colors.join(','), '"',
+ ' opacity="', opacity2, '"',
+ ' g_o_:opacity2="', opacity1, '"',
+ ' angle="', angle, '"',
+ ' focusposition="', focus.x, ',', focus.y, '" />');
+ } else {
+ lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity,
+ '" />');
+ }
+
+ lineStr.push('</g_vml_:shape>');
+
+ this.element_.insertAdjacentHTML('beforeEnd', lineStr.join(''));
+ };
+
+ contextPrototype.fill = function() {
+ this.stroke(true);
+ }
+
+ contextPrototype.closePath = function() {
+ this.currentPath_.push({type: 'close'});
+ };
+
+ /**
+ * @private
+ */
+ contextPrototype.getCoords_ = function(aX, aY) {
+ var m = this.m_;
+ return {
+ x: Z * (aX * m[0][0] + aY * m[1][0] + m[2][0]) - Z2,
+ y: Z * (aX * m[0][1] + aY * m[1][1] + m[2][1]) - Z2
+ }
+ };
+
+ contextPrototype.save = function() {
+ var o = {};
+ copyState(this, o);
+ this.aStack_.push(o);
+ this.mStack_.push(this.m_);
+ this.m_ = matrixMultiply(createMatrixIdentity(), this.m_);
+ };
+
+ contextPrototype.restore = function() {
+ copyState(this.aStack_.pop(), this);
+ this.m_ = this.mStack_.pop();
+ };
+
+ function matrixIsFinite(m) {
+ for (var j = 0; j < 3; j++) {
+ for (var k = 0; k < 2; k++) {
+ if (!isFinite(m[j][k]) || isNaN(m[j][k])) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ function setM(ctx, m, updateLineScale) {
+ if (!matrixIsFinite(m)) {
+ return;
+ }
+ ctx.m_ = m;
+
+ if (updateLineScale) {
+ // Get the line scale.
+ // Determinant of this.m_ means how much the area is enlarged by the
+ // transformation. So its square root can be used as a scale factor
+ // for width.
+ var det = m[0][0] * m[1][1] - m[0][1] * m[1][0];
+ ctx.lineScale_ = sqrt(abs(det));
+ }
+ }
+
+ contextPrototype.translate = function(aX, aY) {
+ var m1 = [
+ [1, 0, 0],
+ [0, 1, 0],
+ [aX, aY, 1]
+ ];
+
+ setM(this, matrixMultiply(m1, this.m_), false);
+ };
+
+ contextPrototype.rotate = function(aRot) {
+ var c = mc(aRot);
+ var s = ms(aRot);
+
+ var m1 = [
+ [c, s, 0],
+ [-s, c, 0],
+ [0, 0, 1]
+ ];
+
+ setM(this, matrixMultiply(m1, this.m_), false);
+ };
+
+ contextPrototype.scale = function(aX, aY) {
+ this.arcScaleX_ *= aX;
+ this.arcScaleY_ *= aY;
+ var m1 = [
+ [aX, 0, 0],
+ [0, aY, 0],
+ [0, 0, 1]
+ ];
+
+ setM(this, matrixMultiply(m1, this.m_), true);
+ };
+
+ contextPrototype.transform = function(m11, m12, m21, m22, dx, dy) {
+ var m1 = [
+ [m11, m12, 0],
+ [m21, m22, 0],
+ [dx, dy, 1]
+ ];
+
+ setM(this, matrixMultiply(m1, this.m_), true);
+ };
+
+ contextPrototype.setTransform = function(m11, m12, m21, m22, dx, dy) {
+ var m = [
+ [m11, m12, 0],
+ [m21, m22, 0],
+ [dx, dy, 1]
+ ];
+
+ setM(this, m, true);
+ };
+
+ /******** STUBS ********/
+ contextPrototype.clip = function() {
+ // TODO: Implement
+ };
+
+ contextPrototype.arcTo = function() {
+ // TODO: Implement
+ };
+
+ contextPrototype.createPattern = function() {
+ return new CanvasPattern_;
+ };
+
+ // Gradient / Pattern Stubs
+ function CanvasGradient_(aType) {
+ this.type_ = aType;
+ this.x0_ = 0;
+ this.y0_ = 0;
+ this.r0_ = 0;
+ this.x1_ = 0;
+ this.y1_ = 0;
+ this.r1_ = 0;
+ this.colors_ = [];
+ }
+
+ CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) {
+ aColor = processStyle(aColor);
+ this.colors_.push({offset: aOffset,
+ color: aColor.color,
+ alpha: aColor.alpha});
+ };
+
+ function CanvasPattern_() {}
+
+ // set up externs
+ G_vmlCanvasManager = G_vmlCanvasManager_;
+ CanvasRenderingContext2D = CanvasRenderingContext2D_;
+ CanvasGradient = CanvasGradient_;
+ CanvasPattern = CanvasPattern_;
+
+})();
+
+} // if
+
+if (dhtmlx && dhtmlx._modules)
+ dhtmlx._modules["thirdparty/excanvas/excanvas.js"] = true; \ No newline at end of file