pyk 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- Njk2OTBkYTkzMjA3MTUwYmQ4NjUwYjE1OTU2YmY2Y2UyNjkxMTU5NA==
4
+ MDM1ODViMDUyODQ2MzQ1N2I3NTEwNGViYWRmNzE4ZGYxMjAwNTA2Ng==
5
5
  data.tar.gz: !binary |-
6
- ZDA5ZGYxODIzYjhiNGEwZjQ2ZjhlYjY5NTcyZmY2ZjA5MDVhZjhkOQ==
6
+ MjFlYzM2NDUzYWNkZDk3ZmExOTA2NDgyZjE5Yzc3ZDk3MDI3Y2UwZQ==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- MzgxODZjZWU5YTk3ZjRlNzQxZjM2OGQxNzc3ZGViYjEzN2QyNzQ3YmZhOWM3
10
- ZDY2NWQ5ZTU2NTAwNDljYTJlOWRjOTdmMGRmNjg3MWRjYWQ2ZThmZmMwZTA5
11
- MTFlMWZkZjRlYzUzMGY5OGVlZDVlM2E1NzQ5YTFjMmEzNGU4NDk=
9
+ Y2YzYWViYTcxZjJjMDZkMDg3NGE2NDNlYzdjYzJlMTM0YzQ2YzZlZjdhYTEx
10
+ NmJhYWZkMjQ5ZjMyZWNlMWNkNGZmNGU3MTA4OWJkNDc0N2VmYzE4ZDNmNWM1
11
+ ZmNlZjg4MjU3NWZmM2Q4ZjEyZTlmZDU2NTkxMTI4MTI5M2JhOTg=
12
12
  data.tar.gz: !binary |-
13
- NDBlYzg0MmY5YzA2ZjczYzNlNzUxYTBkNTVlY2EzM2RhMDBjN2U4YTFhZmQw
14
- ZWUzZGQwZGQ3ZmE4NDM0NzlhYzcyMDY0YzllMTk2MWQ5MDhjZGEwNmY1OWY1
15
- ZmFlZGYzZmI4NzJhNTc2ZDNjNTRiMzhkZmM0ZjUzYjVhZTNjOGE=
13
+ YmZlZTBkMmQ2OWQ3ZDVmODAwNTUyNmE4NWM4OWY5ZjhmM2M3OTliNjM1Zjc5
14
+ N2ViYmIzYmI3ZjU5NDNhYzAxZDFlYjI3NzA1M2Y2OTAyN2VjZTBjMTQ3Nzgy
15
+ OWI2MDcwZWM4YWY3ZWQyMzFkOTcyN2ZiZDAzNmQ4NDBlOTNiNjk=
@@ -0,0 +1 @@
1
+ !function(r){function n(r){return r}function t(r,n){for(var t=0,e=n.length,u=Array(e);e>t;++t)u[t]=r[n[t]];return u}function e(r){function n(n,t,e,u){for(;u>e;){var f=e+u>>>1;r(n[f])<t?e=f+1:u=f}return e}function t(n,t,e,u){for(;u>e;){var f=e+u>>>1;t<r(n[f])?u=f:e=f+1}return e}return t.right=t,t.left=n,t}function u(r){function n(r,n,t){for(var u=t-n,f=(u>>>1)+1;--f>0;)e(r,f,u,n);return r}function t(r,n,t){for(var u,f=t-n;--f>0;)u=r[n],r[n]=r[n+f],r[n+f]=u,e(r,1,f,n);return r}function e(n,t,e,u){for(var f,o=n[--u+t],i=r(o);(f=t<<1)<=e&&(e>f&&r(n[u+f])>r(n[u+f+1])&&f++,!(i<=r(n[u+f])));)n[u+t]=n[u+f],t=f;n[u+t]=o}return n.sort=t,n}function f(r){function n(n,e,u,f){var o,i,a,c,l=Array(f=Math.min(u-e,f));for(i=0;f>i;++i)l[i]=n[e++];if(t(l,0,f),u>e){o=r(l[0]);do(a=r(c=n[e])>o)&&(l[0]=c,o=r(t(l,0,f)[0]));while(++e<u)}return l}var t=u(r);return n}function o(r){function n(n,t,e){for(var u=t+1;e>u;++u){for(var f=u,o=n[u],i=r(o);f>t&&r(n[f-1])>i;--f)n[f]=n[f-1];n[f]=o}return n}return n}function i(r){function n(r,n,u){return(U>u-n?e:t)(r,n,u)}function t(t,e,u){var f,o=0|(u-e)/6,i=e+o,a=u-1-o,c=e+u-1>>1,l=c-o,v=c+o,s=t[i],h=r(s),p=t[l],d=r(p),g=t[c],y=r(g),m=t[v],b=r(m),x=t[a],A=r(x);h>d&&(f=s,s=p,p=f,f=h,h=d,d=f),b>A&&(f=m,m=x,x=f,f=b,b=A,A=f),h>y&&(f=s,s=g,g=f,f=h,h=y,y=f),d>y&&(f=p,p=g,g=f,f=d,d=y,y=f),h>b&&(f=s,s=m,m=f,f=h,h=b,b=f),y>b&&(f=g,g=m,m=f,f=y,y=b,b=f),d>A&&(f=p,p=x,x=f,f=d,d=A,A=f),d>y&&(f=p,p=g,g=f,f=d,d=y,y=f),b>A&&(f=m,m=x,x=f,f=b,b=A,A=f);var k=p,O=d,E=m,w=b;t[i]=s,t[l]=t[e],t[c]=g,t[v]=t[u-1],t[a]=x;var M=e+1,U=u-2,z=w>=O&&O>=w;if(z)for(var N=M;U>=N;++N){var C=t[N],S=r(C);if(O>S)N!==M&&(t[N]=t[M],t[M]=C),++M;else if(S>O)for(;;){var q=r(t[U]);{if(!(q>O)){if(O>q){t[N]=t[M],t[M++]=t[U],t[U--]=C;break}t[N]=t[U],t[U--]=C;break}U--}}}else for(var N=M;U>=N;N++){var C=t[N],S=r(C);if(O>S)N!==M&&(t[N]=t[M],t[M]=C),++M;else if(S>w)for(;;){var q=r(t[U]);{if(!(q>w)){O>q?(t[N]=t[M],t[M++]=t[U],t[U--]=C):(t[N]=t[U],t[U--]=C);break}if(U--,N>U)break}}}if(t[e]=t[M-1],t[M-1]=k,t[u-1]=t[U+1],t[U+1]=E,n(t,e,M-1),n(t,U+2,u),z)return t;if(i>M&&U>a){for(var F,q;(F=r(t[M]))<=O&&F>=O;)++M;for(;(q=r(t[U]))<=w&&q>=w;)--U;for(var N=M;U>=N;N++){var C=t[N],S=r(C);if(O>=S&&S>=O)N!==M&&(t[N]=t[M],t[M]=C),M++;else if(w>=S&&S>=w)for(;;){var q=r(t[U]);{if(!(w>=q&&q>=w)){O>q?(t[N]=t[M],t[M++]=t[U],t[U--]=C):(t[N]=t[U],t[U--]=C);break}if(U--,N>U)break}}}}return n(t,M,U+1)}var e=o(r);return n}function a(r){return Array(r)}function c(r,n){return function(t){var e=t.length;return[r.left(t,n,0,e),r.right(t,n,0,e)]}}function l(r,n){var t=n[0],e=n[1];return function(n){var u=n.length;return[r.left(n,t,0,u),r.left(n,e,0,u)]}}function v(r){return[0,r.length]}function s(){return null}function h(){return 0}function p(r){return r+1}function d(r){return r-1}function g(r){return function(n,t){return n+ +r(t)}}function y(r){return function(n,t){return n-r(t)}}function m(){function r(r){var n=w,t=r.length;return t&&(E=E.concat(r),N=S(N,w+=t),F.forEach(function(e){e(r,n,t)})),O}function e(){for(var r=b(w,w),n=[],t=0,e=0;w>t;++t)N[t]?r[t]=e++:n.push(t);C.forEach(function(r){r(0,[],n)}),R.forEach(function(n){n(r)});for(var u,t=0,e=0;w>t;++t)(u=N[t])&&(t!==e&&(N[e]=u,E[e]=E[t]),++e);for(E.length=e;w>e;)N[--w]=0}function o(r){function e(n,e,u){T=n.map(r),V=$(x(u),0,u),T=t(T,V);var f,o=_(T),i=o[0],a=o[1];if(W)for(f=0;u>f;++f)W(T[f],f)||(N[V[f]+e]|=Y);else{for(f=0;i>f;++f)N[V[f]+e]|=Y;for(f=a;u>f;++f)N[V[f]+e]|=Y}if(!e)return P=T,Q=V,tn=i,en=a,void 0;var c=P,l=Q,v=0,s=0;for(P=Array(w),Q=b(w,w),f=0;e>v&&u>s;++f)c[v]<T[s]?(P[f]=c[v],Q[f]=l[v++]):(P[f]=T[s],Q[f]=V[s++]+e);for(;e>v;++v,++f)P[f]=c[v],Q[f]=l[v];for(;u>s;++s,++f)P[f]=T[s],Q[f]=V[s]+e;o=_(P),tn=o[0],en=o[1]}function o(r,n,t){rn.forEach(function(r){r(T,V,n,t)}),T=V=null}function a(r){for(var n,t=0,e=0;w>t;++t)N[n=Q[t]]&&(t!==e&&(P[e]=P[t]),Q[e]=r[n],++e);for(P.length=e;w>e;)Q[e++]=0;var u=_(P);tn=u[0],en=u[1]}function m(r){var n=r[0],t=r[1];if(W)return W=null,G(function(r,e){return e>=n&&t>e}),tn=n,en=t,X;var e,u,f,o=[],i=[];if(tn>n)for(e=n,u=Math.min(tn,t);u>e;++e)N[f=Q[e]]^=Y,o.push(f);else if(n>tn)for(e=tn,u=Math.min(n,en);u>e;++e)N[f=Q[e]]^=Y,i.push(f);if(t>en)for(e=Math.max(n,en),u=t;u>e;++e)N[f=Q[e]]^=Y,o.push(f);else if(en>t)for(e=Math.max(tn,t),u=en;u>e;++e)N[f=Q[e]]^=Y,i.push(f);return tn=n,en=t,C.forEach(function(r){r(Y,o,i)}),X}function O(r){return null==r?B():Array.isArray(r)?j(r):"function"==typeof r?D(r):z(r)}function z(r){return m((_=c(k,r))(P))}function j(r){return m((_=l(k,r))(P))}function B(){return m((_=v)(P))}function D(r){return _=v,G(W=r),tn=0,en=w,X}function G(r){var n,t,e,u=[],f=[];for(n=0;w>n;++n)!(N[t=Q[n]]&Y)^(e=r(P[n],n))&&(e?(N[t]&=Z,u.push(t)):(N[t]|=Y,f.push(t)));C.forEach(function(r){r(Y,u,f)})}function H(r){for(var n,t=[],e=en;--e>=tn&&r>0;)N[n=Q[e]]||(t.push(E[n]),--r);return t}function I(r){for(var n,t=[],e=tn;en>e&&r>0;)N[n=Q[e]]||(t.push(E[n]),--r),e++;return t}function J(r){function t(n,t,e,u){function f(){++T===L&&(m=q(m,K<<=1),B=q(B,K),L=A(K))}var l,v,h,p,d,g,y=j,m=b(T,L),x=H,k=J,O=T,M=0,U=0;for(X&&(x=k=s),j=Array(T),T=0,B=O>1?S(B,w):b(w,L),O&&(h=(v=y[0]).key);u>U&&!((p=r(n[U]))>=p);)++U;for(;u>U;){for(v&&p>=h?(d=v,g=h,m[M]=T,(v=y[++M])&&(h=v.key)):(d={key:p,value:k()},g=p),j[T]=d;!(p>g||(B[l=t[U]+e]=T,N[l]&Z||(d.value=x(d.value,E[l])),++U>=u));)p=r(n[U]);f()}for(;O>M;)j[m[M]=T]=y[M++],f();if(T>M)for(M=0;e>M;++M)B[M]=m[B[M]];l=C.indexOf(V),T>1?(V=o,W=a):(1===T?(V=i,W=c):(V=s,W=s),B=null),C[l]=V}function e(){if(T>1){for(var r=T,n=j,t=b(r,r),e=0,u=0;w>e;++e)N[e]&&(t[B[u]=B[e]]=1,++u);for(j=[],T=0,e=0;r>e;++e)t[e]&&(t[e]=T++,j.push(n[e]));if(T>1)for(var e=0;u>e;++e)B[e]=t[B[e]];else B=null;C[C.indexOf(V)]=T>1?(W=a,V=o):1===T?(W=c,V=i):W=V=s}else if(1===T){for(var e=0;w>e;++e)if(N[e])return;j=[],T=0,C[C.indexOf(V)]=V=W=s}}function o(r,n,t){if(r!==Y&&!X){var e,u,f,o;for(e=0,f=n.length;f>e;++e)N[u=n[e]]&Z||(o=j[B[u]],o.value=H(o.value,E[u]));for(e=0,f=t.length;f>e;++e)(N[u=t[e]]&Z)===r&&(o=j[B[u]],o.value=I(o.value,E[u]))}}function i(r,n,t){if(r!==Y&&!X){var e,u,f,o=j[0];for(e=0,f=n.length;f>e;++e)N[u=n[e]]&Z||(o.value=H(o.value,E[u]));for(e=0,f=t.length;f>e;++e)(N[u=t[e]]&Z)===r&&(o.value=I(o.value,E[u]))}}function a(){var r,n;for(r=0;T>r;++r)j[r].value=J();for(r=0;w>r;++r)N[r]&Z||(n=j[B[r]],n.value=H(n.value,E[r]))}function c(){var r,n=j[0];for(n.value=J(),r=0;w>r;++r)N[r]&Z||(n.value=H(n.value,E[r]))}function l(){return X&&(W(),X=!1),j}function v(r){var n=D(l(),0,j.length,r);return G.sort(n,0,n.length)}function m(r,n,t){return H=r,I=n,J=t,X=!0,F}function x(){return m(p,d,h)}function k(r){return m(g(r),y(r),h)}function O(r){function n(n){return r(n.value)}return D=f(n),G=u(n),F}function M(){return O(n)}function U(){return T}function z(){var r=C.indexOf(V);return r>=0&&C.splice(r,1),r=rn.indexOf(t),r>=0&&rn.splice(r,1),r=R.indexOf(e),r>=0&&R.splice(r,1),F}var F={top:v,all:l,reduce:m,reduceCount:x,reduceSum:k,order:O,orderNatural:M,size:U,dispose:z,remove:z};nn.push(F);var j,B,D,G,H,I,J,K=8,L=A(K),T=0,V=s,W=s,X=!0;return arguments.length<1&&(r=n),C.push(V),rn.push(t),R.push(e),t(P,Q,0,w),x().orderNatural()}function K(){var r=J(s),n=r.all;return delete r.all,delete r.top,delete r.order,delete r.orderNatural,delete r.size,r.value=function(){return n()[0].value},r}function L(){nn.forEach(function(r){r.dispose()});var r=F.indexOf(e);for(r>=0&&F.splice(r,1),r=F.indexOf(o),r>=0&&F.splice(r,1),r=R.indexOf(a),r>=0&&R.splice(r,1),r=0;w>r;++r)N[r]&=Z;return M&=Z,X}var P,Q,T,V,W,X={filter:O,filterExact:z,filterRange:j,filterFunction:D,filterAll:B,top:H,bottom:I,group:J,groupAll:K,dispose:L,remove:L},Y=~M&-~M,Z=~Y,$=i(function(r){return T[r]}),_=v,rn=[],nn=[],tn=0,en=0;return F.unshift(e),F.push(o),R.push(a),M|=Y,(U>=32?!Y:M&(1<<U)-1)&&(N=q(N,U<<=1)),e(E,0,w),o(E,0,w),X}function a(){function r(r,n){var t;if(!m)for(t=n;w>t;++t)N[t]||(a=c(a,E[t]))}function n(r,n,t){var e,u,f;if(!m){for(e=0,f=n.length;f>e;++e)N[u=n[e]]||(a=c(a,E[u]));for(e=0,f=t.length;f>e;++e)N[u=t[e]]===r&&(a=l(a,E[u]))}}function t(){var r;for(a=v(),r=0;w>r;++r)N[r]||(a=c(a,E[r]))}function e(r,n,t){return c=r,l=n,v=t,m=!0,s}function u(){return e(p,d,h)}function f(r){return e(g(r),y(r),h)}function o(){return m&&(t(),m=!1),a}function i(){var t=C.indexOf(n);return t>=0&&C.splice(t),t=F.indexOf(r),t>=0&&F.splice(t),s}var a,c,l,v,s={reduce:e,reduceCount:u,reduceSum:f,value:o,dispose:i,remove:i},m=!0;return C.push(n),F.push(r),r(E,0,w),u()}function m(){return w}var O={add:r,remove:e,dimension:o,groupAll:a,size:m},E=[],w=0,M=0,U=8,N=z(0),C=[],F=[],R=[];return arguments.length?r(arguments[0]):O}function b(r,n){return(257>n?z:65537>n?N:C)(r)}function x(r){for(var n=b(r,r),t=-1;++t<r;)n[t]=t;return n}function A(r){return 8===r?256:16===r?65536:4294967296}m.version="1.3.5",m.permute=t;var k=m.bisect=e(n);k.by=e;var O=m.heap=u(n);O.by=u;var E=m.heapselect=f(n);E.by=f;var w=m.insertionsort=o(n);w.by=o;var M=m.quicksort=i(n);M.by=i;var U=32,z=a,N=a,C=a,S=n,q=n;"undefined"!=typeof Uint8Array&&(z=function(r){return new Uint8Array(r)},N=function(r){return new Uint16Array(r)},C=function(r){return new Uint32Array(r)},S=function(r,n){if(r.length>=n)return r;var t=new r.constructor(n);return t.set(r),t},q=function(r,n){var t;switch(n){case 16:t=N(r.length);break;case 32:t=C(r.length);break;default:throw Error("invalid array width!")}return t.set(r),t}),r.crossfilter=m}(this);
@@ -0,0 +1,4078 @@
1
+ /*!
2
+ * dc 1.6.0-dev
3
+ * http://nickqizhu.github.io/dc.js/
4
+ * Copyright 2012 Nick Zhu and other contributors
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+
20
+ dc = (function(){
21
+ 'use strict';
22
+
23
+ var dc = {
24
+ version: "1.6.0-dev",
25
+ constants: {
26
+ CHART_CLASS: "dc-chart",
27
+ DEBUG_GROUP_CLASS: "debug",
28
+ STACK_CLASS: "stack",
29
+ DESELECTED_CLASS: "deselected",
30
+ SELECTED_CLASS: "selected",
31
+ NODE_INDEX_NAME: "__index__",
32
+ GROUP_INDEX_NAME: "__group_index__",
33
+ DEFAULT_CHART_GROUP: "__default_chart_group__",
34
+ EVENT_DELAY: 40,
35
+ NEGLIGIBLE_NUMBER: 1e-10
36
+ },
37
+ _renderlet: null
38
+ };
39
+
40
+ dc.chartRegistry = function() {
41
+ // chartGroup:string => charts:array
42
+ var _chartMap = {};
43
+
44
+ function initializeChartGroup(group) {
45
+ if (!group)
46
+ group = dc.constants.DEFAULT_CHART_GROUP;
47
+
48
+ if (!_chartMap[group])
49
+ _chartMap[group] = [];
50
+
51
+ return group;
52
+ }
53
+
54
+ return {
55
+ has: function(chart) {
56
+ for (var e in _chartMap) {
57
+ if (_chartMap[e].indexOf(chart) >= 0)
58
+ return true;
59
+ }
60
+ return false;
61
+ },
62
+
63
+ register: function(chart, group) {
64
+ group = initializeChartGroup(group);
65
+ _chartMap[group].push(chart);
66
+ },
67
+
68
+ clear: function() {
69
+ _chartMap = {};
70
+ },
71
+
72
+ list: function(group) {
73
+ group = initializeChartGroup(group);
74
+ return _chartMap[group];
75
+ }
76
+ };
77
+ }();
78
+
79
+ dc.registerChart = function(chart, group) {
80
+ dc.chartRegistry.register(chart, group);
81
+ };
82
+
83
+ dc.hasChart = function(chart) {
84
+ return dc.chartRegistry.has(chart);
85
+ };
86
+
87
+ dc.deregisterAllCharts = function() {
88
+ dc.chartRegistry.clear();
89
+ };
90
+
91
+ dc.filterAll = function(group) {
92
+ var charts = dc.chartRegistry.list(group);
93
+ for (var i = 0; i < charts.length; ++i) {
94
+ charts[i].filterAll();
95
+ }
96
+ };
97
+
98
+ dc.renderAll = function(group) {
99
+ var charts = dc.chartRegistry.list(group);
100
+ for (var i = 0; i < charts.length; ++i) {
101
+ charts[i].render();
102
+ }
103
+
104
+ if(dc._renderlet !== null)
105
+ dc._renderlet(group);
106
+ };
107
+
108
+ dc.redrawAll = function(group) {
109
+ var charts = dc.chartRegistry.list(group);
110
+ for (var i = 0; i < charts.length; ++i) {
111
+ charts[i].redraw();
112
+ }
113
+
114
+ if(dc._renderlet !== null)
115
+ dc._renderlet(group);
116
+ };
117
+
118
+ dc.transition = function(selections, duration, callback) {
119
+ if (duration <= 0 || duration === undefined)
120
+ return selections;
121
+
122
+ var s = selections
123
+ .transition()
124
+ .duration(duration);
125
+
126
+ if (callback instanceof Function) {
127
+ callback(s);
128
+ }
129
+
130
+ return s;
131
+ };
132
+
133
+ dc.units = {};
134
+ dc.units.integers = function(s, e) {
135
+ return Math.abs(e - s);
136
+ };
137
+
138
+ dc.units.ordinal = function(s, e, domain){
139
+ return domain;
140
+ };
141
+ dc.units.fp = {};
142
+ dc.units.fp.precision = function(precision){
143
+ var _f = function(s, e){return Math.ceil(Math.abs((e-s)/_f.resolution));};
144
+ _f.resolution = precision;
145
+ return _f;
146
+ };
147
+
148
+ dc.round = {};
149
+ dc.round.floor = function(n) {
150
+ return Math.floor(n);
151
+ };
152
+ dc.round.ceil = function(n) {
153
+ return Math.ceil(n);
154
+ };
155
+ dc.round.round = function(n) {
156
+ return Math.round(n);
157
+ };
158
+
159
+ dc.override = function(obj, functionName, newFunction) {
160
+ var existingFunction = obj[functionName];
161
+ obj["_" + functionName] = existingFunction;
162
+ obj[functionName] = newFunction;
163
+ };
164
+
165
+ dc.renderlet = function(_){
166
+ if(!arguments.length) return dc._renderlet;
167
+ dc._renderlet = _;
168
+ return dc;
169
+ };
170
+
171
+ dc.instanceOfChart = function (o) {
172
+ return o instanceof Object && o.__dc_flag__;
173
+ };
174
+
175
+ dc.errors = {};
176
+
177
+ dc.errors.Exception = function(msg) {
178
+ var _msg = msg !== undefined ? msg : "Unexpected internal error";
179
+
180
+ this.message = _msg;
181
+
182
+ this.toString = function(){
183
+ return _msg;
184
+ };
185
+ };
186
+
187
+ dc.errors.InvalidStateException = function() {
188
+ dc.errors.Exception.apply(this, arguments);
189
+ };
190
+
191
+ dc.dateFormat = d3.time.format("%m/%d/%Y");
192
+
193
+ dc.printers = {};
194
+
195
+ dc.printers.filters = function (filters) {
196
+ var s = "";
197
+
198
+ for (var i = 0; i < filters.length; ++i) {
199
+ if (i > 0) s += ", ";
200
+ s += dc.printers.filter(filters[i]);
201
+ }
202
+
203
+ return s;
204
+ };
205
+
206
+ dc.printers.filter = function (filter) {
207
+ var s = "";
208
+
209
+ if (filter) {
210
+ if (filter instanceof Array) {
211
+ if (filter.length >= 2)
212
+ s = "[" + dc.utils.printSingleValue(filter[0]) + " -> " + dc.utils.printSingleValue(filter[1]) + "]";
213
+ else if (filter.length >= 1)
214
+ s = dc.utils.printSingleValue(filter[0]);
215
+ } else {
216
+ s = dc.utils.printSingleValue(filter);
217
+ }
218
+ }
219
+
220
+ return s;
221
+ };
222
+
223
+ dc.utils = {};
224
+
225
+ dc.utils.printSingleValue = function (filter) {
226
+ var s = "" + filter;
227
+
228
+ if (filter instanceof Date)
229
+ s = dc.dateFormat(filter);
230
+ else if (typeof(filter) == "string")
231
+ s = filter;
232
+ else if (dc.utils.isFloat(filter))
233
+ s = dc.utils.printSingleValue.fformat(filter);
234
+ else if (dc.utils.isInteger(filter))
235
+ s = Math.round(filter);
236
+
237
+ return s;
238
+ };
239
+ dc.utils.printSingleValue.fformat = d3.format(".2f");
240
+
241
+ dc.utils.add = function (l, r) {
242
+ if (typeof r === "string")
243
+ r = r.replace("%", "");
244
+
245
+ if (l instanceof Date) {
246
+ if (typeof r === "string") r = +r;
247
+ var d = new Date();
248
+ d.setTime(l.getTime());
249
+ d.setDate(l.getDate() + r);
250
+ return d;
251
+ } else if (typeof r === "string") {
252
+ var percentage = (+r / 100);
253
+ return l > 0 ? l * (1 + percentage) : l * (1 - percentage);
254
+ } else {
255
+ return l + r;
256
+ }
257
+ };
258
+
259
+ dc.utils.subtract = function (l, r) {
260
+ if (typeof r === "string")
261
+ r = r.replace("%", "");
262
+
263
+ if (l instanceof Date) {
264
+ if (typeof r === "string") r = +r;
265
+ var d = new Date();
266
+ d.setTime(l.getTime());
267
+ d.setDate(l.getDate() - r);
268
+ return d;
269
+ } else if (typeof r === "string") {
270
+ var percentage = (+r / 100);
271
+ return l < 0 ? l * (1 + percentage) : l * (1 - percentage);
272
+ } else {
273
+ return l - r;
274
+ }
275
+ };
276
+
277
+ dc.utils.GroupStack = function () {
278
+ var _dataLayers = [[ ]];
279
+ var _groups = [];
280
+ var _defaultAccessor;
281
+
282
+ function initializeDataLayer(i) {
283
+ if (!_dataLayers[i])
284
+ _dataLayers[i] = [];
285
+ }
286
+
287
+ this.setDataPoint = function (layerIndex, pointIndex, data) {
288
+ initializeDataLayer(layerIndex);
289
+ _dataLayers[layerIndex][pointIndex] = data;
290
+ };
291
+
292
+ this.getDataPoint = function (x, y) {
293
+ initializeDataLayer(x);
294
+ var dataPoint = _dataLayers[x][y];
295
+ if (dataPoint === undefined)
296
+ dataPoint = 0;
297
+ return dataPoint;
298
+ };
299
+
300
+ this.addGroup = function (group, accessor) {
301
+ if (!accessor)
302
+ accessor = _defaultAccessor;
303
+ _groups.push([group, accessor]);
304
+ return _groups.length - 1;
305
+ };
306
+
307
+ this.getGroupByIndex = function (index) {
308
+ return _groups[index][0];
309
+ };
310
+
311
+ this.getAccessorByIndex = function (index) {
312
+ return _groups[index][1];
313
+ };
314
+
315
+ this.size = function () {
316
+ return _groups.length;
317
+ };
318
+
319
+ this.clear = function () {
320
+ _dataLayers = [];
321
+ _groups = [];
322
+ };
323
+
324
+ this.setDefaultAccessor = function (retriever) {
325
+ _defaultAccessor = retriever;
326
+ };
327
+
328
+ this.getDataLayers = function () {
329
+ return _dataLayers;
330
+ };
331
+
332
+ this.toLayers = function () {
333
+ var layers = [];
334
+
335
+ for (var i = 0; i < _dataLayers.length; ++i) {
336
+ var layer = {index: i, points: []};
337
+ var dataPoints = _dataLayers[i];
338
+
339
+ for (var j = 0; j < dataPoints.length; ++j)
340
+ layer.points.push(dataPoints[j]);
341
+
342
+ layers.push(layer);
343
+ }
344
+
345
+ return layers;
346
+ };
347
+ };
348
+
349
+ dc.utils.isNumber = function(n) {
350
+ return n===+n;
351
+ };
352
+
353
+ dc.utils.isFloat = function (n) {
354
+ return n===+n && n!==(n|0);
355
+ };
356
+
357
+ dc.utils.isInteger = function (n) {
358
+ return n===+n && n===(n|0);
359
+ };
360
+
361
+ dc.utils.isNegligible = function (max) {
362
+ return max === undefined || (max < dc.constants.NEGLIGIBLE_NUMBER && max > -dc.constants.NEGLIGIBLE_NUMBER);
363
+ };
364
+
365
+ dc.utils.groupMax = function (group, accessor) {
366
+ var max = d3.max(group.all(), function (e) {
367
+ return accessor(e);
368
+ });
369
+ if (dc.utils.isNegligible(max)) max = 0;
370
+ return max;
371
+ };
372
+
373
+ dc.utils.groupMin = function (group, accessor) {
374
+ var min = d3.min(group.all(), function (e) {
375
+ return accessor(e);
376
+ });
377
+ if (dc.utils.isNegligible(min)) min = 0;
378
+ return min;
379
+ };
380
+
381
+ dc.utils.nameToId = function (name) {
382
+ return name.toLowerCase().replace(/[\s]/g, "_").replace(/[\.']/g, "");
383
+ };
384
+
385
+ dc.utils.appendOrSelect = function (parent, name) {
386
+ var element = parent.select(name);
387
+ if (element.empty()) element = parent.append(name);
388
+ return element;
389
+ };
390
+
391
+ dc.utils.createLegendable = function (chart, group, index, accessor) {
392
+ var legendable = {name: chart.getGroupName(group, accessor), data: group};
393
+ if (typeof chart.colors === 'function') legendable.color = chart.colors()(index);
394
+ return legendable;
395
+ };
396
+
397
+ dc.utils.safeNumber = function(n){return dc.utils.isNumber(+n)?+n:0;};
398
+
399
+ dc.events = {
400
+ current: null
401
+ };
402
+
403
+ dc.events.trigger = function(closure, delay) {
404
+ if (!delay){
405
+ closure();
406
+ return;
407
+ }
408
+
409
+ dc.events.current = closure;
410
+
411
+ setTimeout(function() {
412
+ if (closure == dc.events.current)
413
+ closure();
414
+ }, delay);
415
+ };
416
+
417
+ dc.cumulative = {};
418
+
419
+ dc.cumulative.Base = function() {
420
+ this._keyIndex = [];
421
+ this._map = {};
422
+
423
+ this.sanitizeKey = function(key) {
424
+ key = key + "";
425
+ return key;
426
+ };
427
+
428
+ this.clear = function() {
429
+ this._keyIndex = [];
430
+ this._map = {};
431
+ };
432
+
433
+ this.size = function() {
434
+ return this._keyIndex.length;
435
+ };
436
+
437
+ this.getValueByKey = function(key) {
438
+ key = this.sanitizeKey(key);
439
+ var value = this._map[key];
440
+ return value;
441
+ };
442
+
443
+ this.setValueByKey = function(key, value) {
444
+ key = this.sanitizeKey(key);
445
+ return this._map[key] = value;
446
+ };
447
+
448
+ this.indexOfKey = function(key) {
449
+ key = this.sanitizeKey(key);
450
+ return this._keyIndex.indexOf(key);
451
+ };
452
+
453
+ this.addToIndex = function(key) {
454
+ key = this.sanitizeKey(key);
455
+ this._keyIndex.push(key);
456
+ };
457
+
458
+ this.getKeyByIndex = function(index) {
459
+ return this._keyIndex[index];
460
+ };
461
+ };
462
+
463
+ dc.cumulative.Sum = function() {
464
+ dc.cumulative.Base.apply(this, arguments);
465
+
466
+ this.add = function(key, value) {
467
+ if (!value)
468
+ value = 0;
469
+
470
+ if (this.getValueByKey(key) === undefined) {
471
+ this.addToIndex(key);
472
+ this.setValueByKey(key, value);
473
+ } else {
474
+ this.setValueByKey(key, this.getValueByKey(key) + value);
475
+ }
476
+ };
477
+
478
+ this.minus = function(key, value) {
479
+ this.setValueByKey(key, this.getValueByKey(key) - value);
480
+ };
481
+
482
+ this.cumulativeSum = function(key) {
483
+ var keyIndex = this.indexOfKey(key);
484
+ if (keyIndex < 0) return 0;
485
+ var cumulativeValue = 0;
486
+ for (var i = 0; i <= keyIndex; ++i) {
487
+ var k = this.getKeyByIndex(i);
488
+ cumulativeValue += this.getValueByKey(k);
489
+ }
490
+ return cumulativeValue;
491
+ };
492
+ };
493
+ dc.cumulative.Sum.prototype = new dc.cumulative.Base();
494
+
495
+ dc.cumulative.CountUnique = function() {
496
+ dc.cumulative.Base.apply(this, arguments);
497
+
498
+ function hashSize(hash) {
499
+ var size = 0, key;
500
+ for (key in hash) {
501
+ if (hash.hasOwnProperty(key)) size++;
502
+ }
503
+ return size;
504
+ }
505
+
506
+ this.add = function(key, e) {
507
+ if (this.getValueByKey(key) === undefined) {
508
+ this.setValueByKey(key, {});
509
+ this.addToIndex(key);
510
+ }
511
+
512
+ if (e !== undefined) {
513
+ if (this.getValueByKey(key)[e] === undefined)
514
+ this.getValueByKey(key)[e] = 0;
515
+
516
+ this.getValueByKey(key)[e] += 1;
517
+ }
518
+ };
519
+
520
+ this.minus = function(key, e) {
521
+ this.getValueByKey(key)[e] -= 1;
522
+ if (this.getValueByKey(key)[e] <= 0)
523
+ delete this.getValueByKey(key)[e];
524
+ };
525
+
526
+ this.count = function(key) {
527
+ return hashSize(this.getValueByKey(key));
528
+ };
529
+
530
+ this.cumulativeCount = function(key) {
531
+ var keyIndex = this.indexOfKey(key);
532
+ if (keyIndex < 0) return 0;
533
+ var cumulativeCount = 0;
534
+ for (var i = 0; i <= keyIndex; ++i) {
535
+ var k = this.getKeyByIndex(i);
536
+ cumulativeCount += this.count(k);
537
+ }
538
+ return cumulativeCount;
539
+ };
540
+ };
541
+ dc.cumulative.CountUnique.prototype = new dc.cumulative.Base();
542
+
543
+ dc.baseChart = function (_chart) {
544
+ _chart.__dc_flag__ = true;
545
+
546
+ var _dimension;
547
+ var _group;
548
+
549
+ var _anchor;
550
+ var _root;
551
+ var _svg;
552
+
553
+ var _width = 200, _height = 200;
554
+
555
+ var _keyAccessor = function (d) {
556
+ return d.key;
557
+ };
558
+ var _valueAccessor = function (d) {
559
+ return d.value;
560
+ };
561
+ var _ordering = function (p) {
562
+ return p.key;
563
+ };
564
+
565
+ var _label = function (d) {
566
+ return d.key;
567
+ };
568
+ var _renderLabel = false;
569
+
570
+ var _title = function (d) {
571
+ return d.key + ": " + d.value;
572
+ };
573
+ var _renderTitle = false;
574
+
575
+ var _transitionDuration = 750;
576
+
577
+ var _filterPrinter = dc.printers.filters;
578
+
579
+ var _renderlets = [];
580
+
581
+ var _chartGroup = dc.constants.DEFAULT_CHART_GROUP;
582
+
583
+ var NULL_LISTENER = function (chart) {
584
+ };
585
+ var _listeners = {
586
+ preRender: NULL_LISTENER,
587
+ postRender: NULL_LISTENER,
588
+ preRedraw: NULL_LISTENER,
589
+ postRedraw: NULL_LISTENER,
590
+ filtered: NULL_LISTENER,
591
+ zoomed: NULL_LISTENER
592
+ };
593
+ var _legend;
594
+
595
+ var _filters = [];
596
+ var _filterHandler = function (dimension, filters) {
597
+ dimension.filter(null);
598
+
599
+ if (filters.length === 0)
600
+ dimension.filter(null);
601
+ else if (filters.length === 1)
602
+ dimension.filter(filters[0]);
603
+ else
604
+ dimension.filterFunction(function (d) {
605
+ return filters.indexOf(d) >= 0;
606
+ });
607
+
608
+ return filters;
609
+ };
610
+
611
+ _chart.width = function (w) {
612
+ if (!arguments.length) return _width;
613
+ _width = w;
614
+ return _chart;
615
+ };
616
+
617
+ _chart.height = function (h) {
618
+ if (!arguments.length) return _height;
619
+ _height = h;
620
+ return _chart;
621
+ };
622
+
623
+ _chart.dimension = function (d) {
624
+ if (!arguments.length) return _dimension;
625
+ _dimension = d;
626
+ _chart.expireCache();
627
+ return _chart;
628
+ };
629
+
630
+ _chart.group = function (g, name) {
631
+ if (!arguments.length) return _group;
632
+ _group = g;
633
+ _chart.expireCache();
634
+ if (typeof name === 'string') _chart.setGroupName(_group, name);
635
+ return _chart;
636
+ };
637
+
638
+ _chart.setGroupName = function (g, name, accessor) {
639
+ if (!g.__names__) g.__names__ = {};
640
+ g.__names__[groupNameKey(accessor)] = name;
641
+ };
642
+
643
+ function groupNameKey(accessor) {
644
+ var defaultKey = "default";
645
+ return accessor ? (accessor == _chart.valueAccessor() ? defaultKey : accessor) : defaultKey;
646
+ }
647
+
648
+ _chart.getGroupName = function (g, accessor) {
649
+ if (!g.__names__) g.__names__ = {};
650
+ return g.__names__[groupNameKey(accessor)];
651
+ };
652
+
653
+ _chart.ordering = function(o) {
654
+ if (!arguments.length) return _ordering;
655
+ _ordering = o;
656
+ _chart.expireCache();
657
+ return _chart;
658
+ };
659
+
660
+ _chart.computeOrderedGroups = function(arr) {
661
+ var data = arr ? arr : _chart.group().all().slice(0); // clone
662
+ if(data.length < 2)
663
+ return data;
664
+ var sort = crossfilter.quicksort.by(_chart.ordering());
665
+ return sort(data,0,data.length);
666
+ };
667
+
668
+ _chart.filterAll = function () {
669
+ return _chart.filter(null);
670
+ };
671
+
672
+ _chart.dataSet = function () {
673
+ return _dimension !== undefined && _group !== undefined;
674
+ };
675
+
676
+ _chart.select = function (s) {
677
+ return _root.select(s);
678
+ };
679
+
680
+ _chart.selectAll = function (s) {
681
+ return _root ? _root.selectAll(s) : null;
682
+ };
683
+
684
+ _chart.anchor = function (a, chartGroup) {
685
+ if (!arguments.length) return _anchor;
686
+ if (dc.instanceOfChart(a)) {
687
+ _anchor = a.anchor();
688
+ _root = a.root();
689
+ } else {
690
+ _anchor = a;
691
+ _root = d3.select(_anchor);
692
+ _root.classed(dc.constants.CHART_CLASS, true);
693
+ dc.registerChart(_chart, chartGroup);
694
+ }
695
+ _chartGroup = chartGroup;
696
+ return _chart;
697
+ };
698
+
699
+ _chart.anchorName = function () {
700
+ var a = _chart.anchor();
701
+ if (a && a.id) return a.id;
702
+ if (a) return a.replace('#','');
703
+ return '';
704
+ };
705
+
706
+ _chart.root = function (r) {
707
+ if (!arguments.length) return _root;
708
+ _root = r;
709
+ return _chart;
710
+ };
711
+
712
+ _chart.svg = function (_) {
713
+ if (!arguments.length) return _svg;
714
+ _svg = _;
715
+ return _chart;
716
+ };
717
+
718
+ _chart.resetSvg = function () {
719
+ _chart.select("svg").remove();
720
+ return _chart.generateSvg();
721
+ };
722
+
723
+ _chart.generateSvg = function () {
724
+ _svg = _chart.root().append("svg")
725
+ .attr("width", _chart.width())
726
+ .attr("height", _chart.height());
727
+ return _svg;
728
+ };
729
+
730
+ _chart.filterPrinter = function (_) {
731
+ if (!arguments.length) return _filterPrinter;
732
+ _filterPrinter = _;
733
+ return _chart;
734
+ };
735
+
736
+ _chart.turnOnControls = function () {
737
+ if (_root) {
738
+ _chart.selectAll(".reset").style("display", null);
739
+ _chart.selectAll(".filter").text(_filterPrinter(_chart.filters())).style("display", null);
740
+ }
741
+ return _chart;
742
+ };
743
+
744
+ _chart.turnOffControls = function () {
745
+ if (_root) {
746
+ _chart.selectAll(".reset").style("display", "none");
747
+ _chart.selectAll(".filter").style("display", "none").text(_chart.filter());
748
+ }
749
+ return _chart;
750
+ };
751
+
752
+ _chart.transitionDuration = function (d) {
753
+ if (!arguments.length) return _transitionDuration;
754
+ _transitionDuration = d;
755
+ return _chart;
756
+ };
757
+
758
+ _chart.render = function () {
759
+ _listeners.preRender(_chart);
760
+
761
+ if (_dimension === undefined)
762
+ throw new dc.errors.InvalidStateException("Mandatory attribute chart.dimension is missing on chart[#"
763
+ + _chart.anchorName() + "]");
764
+
765
+ if (_group === undefined)
766
+ throw new dc.errors.InvalidStateException("Mandatory attribute chart.group is missing on chart[#"
767
+ + _chart.anchorName() + "]");
768
+
769
+ var result = _chart.doRender();
770
+
771
+ if (_legend) _legend.render();
772
+
773
+ _chart.activateRenderlets("postRender");
774
+
775
+ return result;
776
+ };
777
+
778
+ _chart.activateRenderlets = function (event) {
779
+ if (_chart.transitionDuration() > 0 && _svg) {
780
+ _svg.transition().duration(_chart.transitionDuration())
781
+ .each("end", function () {
782
+ runAllRenderlets();
783
+ if (event) _listeners[event](_chart);
784
+ });
785
+ } else {
786
+ runAllRenderlets();
787
+ if (event) _listeners[event](_chart);
788
+ }
789
+ };
790
+
791
+ _chart.redraw = function () {
792
+ _listeners.preRedraw(_chart);
793
+
794
+ var result = _chart.doRedraw();
795
+
796
+ _chart.activateRenderlets("postRedraw");
797
+
798
+ return result;
799
+ };
800
+
801
+ _chart.invokeFilteredListener = function (f) {
802
+ if (f !== undefined) _listeners.filtered(_chart, f);
803
+ };
804
+
805
+ _chart.invokeZoomedListener = function () {
806
+ _listeners.zoomed(_chart);
807
+ };
808
+
809
+ _chart.hasFilter = function (filter) {
810
+ if (!arguments.length) return _filters.length > 0;
811
+ return _filters.indexOf(filter) >= 0;
812
+ };
813
+
814
+ function removeFilter(_) {
815
+ _filters.splice(_filters.indexOf(_), 1);
816
+ applyFilters();
817
+ _chart.invokeFilteredListener(_);
818
+ }
819
+
820
+ function addFilter(_) {
821
+ _filters.push(_);
822
+ applyFilters();
823
+ _chart.invokeFilteredListener(_);
824
+ }
825
+
826
+ function resetFilters() {
827
+ _filters = [];
828
+ applyFilters();
829
+ _chart.invokeFilteredListener(null);
830
+ }
831
+
832
+ function applyFilters() {
833
+ if (_chart.dataSet() && _chart.dimension().filter !== undefined) {
834
+ var fs = _filterHandler(_chart.dimension(), _filters);
835
+ _filters = fs ? fs : _filters;
836
+ }
837
+ }
838
+
839
+ _chart.filter = function (_) {
840
+ if (!arguments.length) return _filters.length > 0 ? _filters[0] : null;
841
+
842
+ if (_ === null) {
843
+ resetFilters();
844
+ } else {
845
+ if (_chart.hasFilter(_))
846
+ removeFilter(_);
847
+ else
848
+ addFilter(_);
849
+ }
850
+
851
+ if (_root !== null && _chart.hasFilter()) {
852
+ _chart.turnOnControls();
853
+ } else {
854
+ _chart.turnOffControls();
855
+ }
856
+
857
+ return _chart;
858
+ };
859
+
860
+ _chart.filters = function () {
861
+ return _filters;
862
+ };
863
+
864
+ _chart.highlightSelected = function (e) {
865
+ d3.select(e).classed(dc.constants.SELECTED_CLASS, true);
866
+ d3.select(e).classed(dc.constants.DESELECTED_CLASS, false);
867
+ };
868
+
869
+ _chart.fadeDeselected = function (e) {
870
+ d3.select(e).classed(dc.constants.SELECTED_CLASS, false);
871
+ d3.select(e).classed(dc.constants.DESELECTED_CLASS, true);
872
+ };
873
+
874
+ _chart.resetHighlight = function (e) {
875
+ d3.select(e).classed(dc.constants.SELECTED_CLASS, false);
876
+ d3.select(e).classed(dc.constants.DESELECTED_CLASS, false);
877
+ };
878
+
879
+ _chart.onClick = function (d) {
880
+ var filter = _chart.keyAccessor()(d);
881
+ dc.events.trigger(function () {
882
+ _chart.filter(filter);
883
+ dc.redrawAll(_chart.chartGroup());
884
+ });
885
+ };
886
+
887
+ _chart.filterHandler = function (_) {
888
+ if (!arguments.length) return _filterHandler;
889
+ _filterHandler = _;
890
+ return _chart;
891
+ };
892
+
893
+ // abstract function stub
894
+ _chart.doRender = function () {
895
+ // do nothing in base, should be overridden by sub-function
896
+ return _chart;
897
+ };
898
+
899
+ _chart.doRedraw = function () {
900
+ // do nothing in base, should be overridden by sub-function
901
+ return _chart;
902
+ };
903
+
904
+ _chart.legendables = function () {
905
+ // do nothing in base, should be overridden by sub-function
906
+ return [];
907
+ };
908
+
909
+ _chart.legendHighlight = function (d) {
910
+ // do nothing in base, should be overridden by sub-function
911
+ };
912
+
913
+ _chart.legendReset = function (d) {
914
+ // do nothing in base, should be overridden by sub-function
915
+ };
916
+
917
+ _chart.keyAccessor = function (_) {
918
+ if (!arguments.length) return _keyAccessor;
919
+ _keyAccessor = _;
920
+ return _chart;
921
+ };
922
+
923
+ _chart.valueAccessor = function (_) {
924
+ if (!arguments.length) return _valueAccessor;
925
+ _valueAccessor = _;
926
+ return _chart;
927
+ };
928
+
929
+ _chart.label = function (_) {
930
+ if (!arguments.length) return _label;
931
+ _label = _;
932
+ _renderLabel = true;
933
+ return _chart;
934
+ };
935
+
936
+ _chart.renderLabel = function (_) {
937
+ if (!arguments.length) return _renderLabel;
938
+ _renderLabel = _;
939
+ return _chart;
940
+ };
941
+
942
+ _chart.title = function (_) {
943
+ if (!arguments.length) return _title;
944
+ _title = _;
945
+ _renderTitle = true;
946
+ return _chart;
947
+ };
948
+
949
+ _chart.renderTitle = function (_) {
950
+ if (!arguments.length) return _renderTitle;
951
+ _renderTitle = _;
952
+ return _chart;
953
+ };
954
+
955
+ _chart.renderlet = function (_) {
956
+ _renderlets.push(_);
957
+ return _chart;
958
+ };
959
+
960
+ function runAllRenderlets() {
961
+ for (var i = 0; i < _renderlets.length; ++i) {
962
+ _renderlets[i](_chart);
963
+ }
964
+ }
965
+
966
+ _chart.chartGroup = function (_) {
967
+ if (!arguments.length) return _chartGroup;
968
+ _chartGroup = _;
969
+ return _chart;
970
+ };
971
+
972
+ _chart.on = function (event, listener) {
973
+ _listeners[event] = listener;
974
+ return _chart;
975
+ };
976
+
977
+ _chart.expireCache = function () {
978
+ // do nothing in base, should be overridden by sub-function
979
+ return _chart;
980
+ };
981
+
982
+ _chart.legend = function (l) {
983
+ if (!arguments.length) return _legend;
984
+ _legend = l;
985
+ _legend.parent(_chart);
986
+ return _chart;
987
+ };
988
+
989
+ return _chart;
990
+ };
991
+
992
+ dc.marginable = function (_chart) {
993
+ var _margin = {top: 10, right: 50, bottom: 30, left: 30};
994
+
995
+ _chart.margins = function (m) {
996
+ if (!arguments.length) return _margin;
997
+ _margin = m;
998
+ return _chart;
999
+ };
1000
+
1001
+ _chart.effectiveWidth = function () {
1002
+ return _chart.width() - _chart.margins().left - _chart.margins().right;
1003
+ };
1004
+
1005
+ _chart.effectiveHeight = function () {
1006
+ return _chart.height() - _chart.margins().top - _chart.margins().bottom;
1007
+ };
1008
+
1009
+ return _chart;
1010
+ };
1011
+
1012
+ dc.coordinateGridChart = function (_chart) {
1013
+ var GRID_LINE_CLASS = "grid-line";
1014
+ var HORIZONTAL_CLASS = "horizontal";
1015
+ var VERTICAL_CLASS = "vertical";
1016
+ var Y_AXIS_LABEL_CLASS = 'y-axis-label';
1017
+ var X_AXIS_LABEL_CLASS = 'x-axis-label';
1018
+ var DEFAULT_AXIS_LABLEL_PADDING = 12;
1019
+
1020
+ _chart = dc.colorChart(dc.marginable(dc.baseChart(_chart)));
1021
+
1022
+ _chart.colors(d3.scale.category10());
1023
+
1024
+ var _parent;
1025
+ var _g;
1026
+ var _chartBodyG;
1027
+
1028
+ var _x;
1029
+ var _xOriginalDomain;
1030
+ var _xAxis = d3.svg.axis();
1031
+ var _xUnits = dc.units.integers;
1032
+ var _xAxisPadding = 0;
1033
+ var _xElasticity = false;
1034
+ var _xAxisLabel;
1035
+ var _xAxisLabelPadding = 0;
1036
+
1037
+ var _y;
1038
+ var _yAxis = d3.svg.axis();
1039
+ var _yAxisPadding = 0;
1040
+ var _yElasticity = false;
1041
+ var _yAxisLabel;
1042
+ var _yAxisLabelPadding = 0;
1043
+
1044
+ var _brush = d3.svg.brush();
1045
+ var _brushOn = true;
1046
+ var _round;
1047
+
1048
+ var _renderHorizontalGridLine = false;
1049
+ var _renderVerticalGridLine = false;
1050
+
1051
+ var _refocused = false;
1052
+ var _unitCount;
1053
+
1054
+ var _zoomScale = [-10, 100]; // -10 to allow zoom out of the original domain
1055
+ var _zoomOutRestrict = false; // restrict zoomOut to the original domain?
1056
+
1057
+ var _rangeChart;
1058
+ var _focusChart;
1059
+
1060
+ var _mouseZoomable = false;
1061
+ var _clipPadding = 0;
1062
+
1063
+ _chart.title(function (d) {
1064
+ return d.data.key + ": " + d.data.value;
1065
+ });
1066
+
1067
+ _chart.rescale = function () {
1068
+ _unitCount = undefined;
1069
+ _chart.xUnitCount();
1070
+ };
1071
+
1072
+ _chart.rangeChart = function (_) {
1073
+ if (!arguments.length) return _rangeChart;
1074
+ _rangeChart = _;
1075
+ _rangeChart.focusChart(_chart);
1076
+ return _chart;
1077
+ };
1078
+
1079
+ _chart.zoomScale = function (_) {
1080
+ if (!arguments.length) return _zoomScale;
1081
+ _zoomScale = _;
1082
+ return _chart;
1083
+ };
1084
+
1085
+ _chart.zoomOutRestrict = function (_) {
1086
+ if (!arguments.length) return _zoomOutRestrict;
1087
+ _zoomOutRestrict = _;
1088
+ return _chart;
1089
+ };
1090
+
1091
+ _chart.generateG = function (parent) {
1092
+ if (parent === undefined)
1093
+ _parent = _chart.svg();
1094
+ else
1095
+ _parent = parent;
1096
+
1097
+ _g = _parent.append("g");
1098
+
1099
+ _chartBodyG = _g.append("g").attr("class", "chart-body")
1100
+ .attr("transform", "translate(" + _chart.margins().left + ", " + _chart.margins().top + ")")
1101
+ .attr("clip-path", "url(#" + getClipPathId() + ")");
1102
+
1103
+ return _g;
1104
+ };
1105
+
1106
+ _chart.g = function (_) {
1107
+ if (!arguments.length) return _g;
1108
+ _g = _;
1109
+ return _chart;
1110
+ };
1111
+
1112
+ _chart.mouseZoomable = function (z) {
1113
+ if (!arguments.length) return _mouseZoomable;
1114
+ _mouseZoomable = z;
1115
+ return _chart;
1116
+ };
1117
+
1118
+ _chart.chartBodyG = function (_) {
1119
+ if (!arguments.length) return _chartBodyG;
1120
+ _chartBodyG = _;
1121
+ return _chart;
1122
+ };
1123
+
1124
+ _chart.x = function (_) {
1125
+ if (!arguments.length) return _x;
1126
+ _x = _;
1127
+ _xOriginalDomain = _x.domain();
1128
+ return _chart;
1129
+ };
1130
+
1131
+ _chart.xOriginalDomain = function () {
1132
+ return _xOriginalDomain;
1133
+ };
1134
+
1135
+ _chart.xUnits = function (_) {
1136
+ if (!arguments.length) return _xUnits;
1137
+ _xUnits = _;
1138
+ return _chart;
1139
+ };
1140
+
1141
+ _chart.xAxis = function (_) {
1142
+ if (!arguments.length) return _xAxis;
1143
+ _xAxis = _;
1144
+ return _chart;
1145
+ };
1146
+
1147
+ _chart.elasticX = function (_) {
1148
+ if (!arguments.length) return _xElasticity;
1149
+ _xElasticity = _;
1150
+ return _chart;
1151
+ };
1152
+
1153
+ _chart.xAxisPadding = function (_) {
1154
+ if (!arguments.length) return _xAxisPadding;
1155
+ _xAxisPadding = _;
1156
+ return _chart;
1157
+ };
1158
+
1159
+ _chart.xUnitCount = function () {
1160
+ if (_unitCount === undefined) {
1161
+ var units = _chart.xUnits()(_chart.x().domain()[0], _chart.x().domain()[1], _chart.x().domain());
1162
+
1163
+ if (units instanceof Array)
1164
+ _unitCount = units.length;
1165
+ else
1166
+ _unitCount = units;
1167
+ }
1168
+
1169
+ return _unitCount;
1170
+ };
1171
+
1172
+ _chart.isOrdinal = function () {
1173
+ return _chart.xUnits() === dc.units.ordinal;
1174
+ };
1175
+
1176
+ _chart.prepareOrdinalXAxis = function (count) {
1177
+ if (!count)
1178
+ count = _chart.xUnitCount();
1179
+ var range = [];
1180
+ var increment = _chart.xAxisLength() / (count + 1);
1181
+ var currentPosition = increment/2;
1182
+ for (var i = 0; i < count; i++) {
1183
+ range[i] = currentPosition;
1184
+ currentPosition += increment;
1185
+ }
1186
+ _x.range(range);
1187
+ };
1188
+
1189
+ function prepareXAxis(g) {
1190
+ if (_chart.elasticX() && !_chart.isOrdinal()) {
1191
+ _x.domain([_chart.xAxisMin(), _chart.xAxisMax()]);
1192
+ }
1193
+ else if (_chart.isOrdinal() && _x.domain().length===0) {
1194
+ _x.domain(_chart.computeOrderedGroups().map(function(kv) { return kv.key; }));
1195
+ }
1196
+
1197
+ if (_chart.isOrdinal()) {
1198
+ _chart.prepareOrdinalXAxis();
1199
+ } else {
1200
+ _x.range([0, _chart.xAxisLength()]);
1201
+ }
1202
+
1203
+ _xAxis = _xAxis.scale(_chart.x()).orient("bottom");
1204
+
1205
+ renderVerticalGridLines(g);
1206
+ }
1207
+
1208
+ _chart.renderXAxis = function (g) {
1209
+ var axisXG = g.selectAll("g.x");
1210
+
1211
+ if (axisXG.empty())
1212
+ axisXG = g.append("g")
1213
+ .attr("class", "axis x")
1214
+ .attr("transform", "translate(" + _chart.margins().left + "," + _chart.xAxisY() + ")");
1215
+
1216
+ var axisXLab = g.selectAll("text."+X_AXIS_LABEL_CLASS);
1217
+ if (axisXLab.empty() && _chart.xAxisLabel())
1218
+ axisXLab = g.append('text')
1219
+ .attr("transform", "translate(" + _chart.xAxisLength() / 2 + "," + (_chart.height() - _xAxisLabelPadding) + ")")
1220
+ .attr('class', X_AXIS_LABEL_CLASS)
1221
+ .attr('text-anchor', 'middle')
1222
+ .text(_chart.xAxisLabel());
1223
+ if (_chart.xAxisLabel() && axisXLab.text() != _chart.xAxisLabel())
1224
+ axisYLab.text(_chart.xAxisLabel());
1225
+
1226
+ dc.transition(axisXG, _chart.transitionDuration())
1227
+ .call(_xAxis);
1228
+ };
1229
+
1230
+ function renderVerticalGridLines(g) {
1231
+ var gridLineG = g.selectAll("g." + VERTICAL_CLASS);
1232
+
1233
+ if (_renderVerticalGridLine) {
1234
+ if (gridLineG.empty())
1235
+ gridLineG = g.insert("g", ":first-child")
1236
+ .attr("class", GRID_LINE_CLASS + " " + VERTICAL_CLASS)
1237
+ .attr("transform", "translate(" + _chart.yAxisX() + "," + _chart.margins().top + ")");
1238
+
1239
+ var ticks = _xAxis.tickValues() ? _xAxis.tickValues() : _x.ticks(_xAxis.ticks()[0]);
1240
+
1241
+ var lines = gridLineG.selectAll("line")
1242
+ .data(ticks);
1243
+
1244
+ // enter
1245
+ var linesGEnter = lines.enter()
1246
+ .append("line")
1247
+ .attr("x1", function (d) {
1248
+ return _x(d);
1249
+ })
1250
+ .attr("y1", _chart.xAxisY() - _chart.margins().top)
1251
+ .attr("x2", function (d) {
1252
+ return _x(d);
1253
+ })
1254
+ .attr("y2", 0)
1255
+ .attr("opacity", 0);
1256
+ dc.transition(linesGEnter, _chart.transitionDuration())
1257
+ .attr("opacity", 1);
1258
+
1259
+ // update
1260
+ dc.transition(lines, _chart.transitionDuration())
1261
+ .attr("x1", function (d) {
1262
+ return _x(d);
1263
+ })
1264
+ .attr("y1", _chart.xAxisY() - _chart.margins().top)
1265
+ .attr("x2", function (d) {
1266
+ return _x(d);
1267
+ })
1268
+ .attr("y2", 0);
1269
+
1270
+ // exit
1271
+ lines.exit().remove();
1272
+ }
1273
+ else {
1274
+ gridLineG.selectAll("line").remove();
1275
+ }
1276
+ }
1277
+
1278
+ _chart.xAxisY = function () {
1279
+ return (_chart.height() - _chart.margins().bottom);
1280
+ };
1281
+
1282
+ _chart.xAxisLength = function () {
1283
+ return _chart.effectiveWidth();
1284
+ };
1285
+
1286
+ _chart.xAxisLabel = function (_,pad) {
1287
+ if (!arguments.length) return _xAxisLabel;
1288
+ _xAxisLabel = _;
1289
+ _chart.margins().bottom -= _xAxisLabelPadding;
1290
+ _xAxisLabelPadding = (pad===undefined) ? DEFAULT_AXIS_LABLEL_PADDING : pad;
1291
+ _chart.margins().bottom += _xAxisLabelPadding;
1292
+ return _chart;
1293
+ };
1294
+
1295
+ function prepareYAxis(g) {
1296
+ if (_y === undefined || _chart.elasticY()) {
1297
+ _y = d3.scale.linear();
1298
+ _y.domain([_chart.yAxisMin(), _chart.yAxisMax()]).rangeRound([_chart.yAxisHeight(), 0]);
1299
+ }
1300
+
1301
+ _y.range([_chart.yAxisHeight(), 0]);
1302
+ _yAxis = _yAxis.scale(_y).orient("left");
1303
+
1304
+ renderHorizontalGridLines(g);
1305
+ }
1306
+
1307
+ _chart.renderYAxis = function (g) {
1308
+ var axisYG = g.selectAll("g.y");
1309
+ if (axisYG.empty())
1310
+ axisYG = g.append("g")
1311
+ .attr("class", "axis y")
1312
+ .attr("transform", "translate(" + _chart.yAxisX() + "," + _chart.margins().top + ")");
1313
+
1314
+ var axisYLab = g.selectAll("text."+Y_AXIS_LABEL_CLASS);
1315
+ if (axisYLab.empty() && _chart.yAxisLabel())
1316
+ axisYLab = g.append('text')
1317
+ .attr("transform", "translate(" + _yAxisLabelPadding + "," + _chart.yAxisHeight()/2 + "),rotate(-90)")
1318
+ .attr('class', Y_AXIS_LABEL_CLASS)
1319
+ .attr('text-anchor', 'middle')
1320
+ .text(_chart.yAxisLabel());
1321
+ if (_chart.yAxisLabel() && axisYLab.text() != _chart.yAxisLabel())
1322
+ axisYLab.text(_chart.yAxisLabel());
1323
+
1324
+ dc.transition(axisYG, _chart.transitionDuration())
1325
+ .call(_yAxis);
1326
+ };
1327
+
1328
+
1329
+ function renderHorizontalGridLines(g) {
1330
+ var gridLineG = g.selectAll("g." + HORIZONTAL_CLASS);
1331
+
1332
+ if (_renderHorizontalGridLine) {
1333
+ var ticks = _yAxis.tickValues() ? _yAxis.tickValues() : _y.ticks(_yAxis.ticks()[0]);
1334
+
1335
+ if (gridLineG.empty())
1336
+ gridLineG = g.insert("g", ":first-child")
1337
+ .attr("class", GRID_LINE_CLASS + " " + HORIZONTAL_CLASS)
1338
+ .attr("transform", "translate(" + _chart.yAxisX() + "," + _chart.margins().top + ")");
1339
+
1340
+ var lines = gridLineG.selectAll("line")
1341
+ .data(ticks);
1342
+
1343
+ // enter
1344
+ var linesGEnter = lines.enter()
1345
+ .append("line")
1346
+ .attr("x1", 1)
1347
+ .attr("y1", function (d) {
1348
+ return _y(d);
1349
+ })
1350
+ .attr("x2", _chart.xAxisLength())
1351
+ .attr("y2", function (d) {
1352
+ return _y(d);
1353
+ })
1354
+ .attr("opacity", 0);
1355
+ dc.transition(linesGEnter, _chart.transitionDuration())
1356
+ .attr("opacity", 1);
1357
+
1358
+ // update
1359
+ dc.transition(lines, _chart.transitionDuration())
1360
+ .attr("x1", 1)
1361
+ .attr("y1", function (d) {
1362
+ return _y(d);
1363
+ })
1364
+ .attr("x2", _chart.xAxisLength())
1365
+ .attr("y2", function (d) {
1366
+ return _y(d);
1367
+ });
1368
+
1369
+ // exit
1370
+ lines.exit().remove();
1371
+ }
1372
+ else {
1373
+ gridLineG.selectAll("line").remove();
1374
+ }
1375
+ }
1376
+
1377
+ _chart.yAxisX = function () {
1378
+ return _chart.margins().left;
1379
+ };
1380
+
1381
+ _chart.yAxisLabel = function (_,pad) {
1382
+ if (!arguments.length) return _yAxisLabel;
1383
+ _yAxisLabel = _;
1384
+ _chart.margins().left -= _yAxisLabelPadding;
1385
+ _yAxisLabelPadding = (pad===undefined) ? DEFAULT_AXIS_LABLEL_PADDING : pad;
1386
+ _chart.margins().left += _yAxisLabelPadding;
1387
+ return _chart;
1388
+ };
1389
+
1390
+ _chart.y = function (_) {
1391
+ if (!arguments.length) return _y;
1392
+ _y = _;
1393
+ return _chart;
1394
+ };
1395
+
1396
+ _chart.yAxis = function (y) {
1397
+ if (!arguments.length) return _yAxis;
1398
+ _yAxis = y;
1399
+ return _chart;
1400
+ };
1401
+
1402
+ _chart.elasticY = function (_) {
1403
+ if (!arguments.length) return _yElasticity;
1404
+ _yElasticity = _;
1405
+ return _chart;
1406
+ };
1407
+
1408
+ _chart.renderHorizontalGridLines = function (_) {
1409
+ if (!arguments.length) return _renderHorizontalGridLine;
1410
+ _renderHorizontalGridLine = _;
1411
+ return _chart;
1412
+ };
1413
+
1414
+ _chart.renderVerticalGridLines = function (_) {
1415
+ if (!arguments.length) return _renderVerticalGridLine;
1416
+ _renderVerticalGridLine = _;
1417
+ return _chart;
1418
+ };
1419
+
1420
+ _chart.xAxisMin = function () {
1421
+ var min = d3.min(_chart.group().all(), function (e) {
1422
+ return _chart.keyAccessor()(e);
1423
+ });
1424
+ return dc.utils.subtract(min, _xAxisPadding);
1425
+ };
1426
+
1427
+ _chart.xAxisMax = function () {
1428
+ var max = d3.max(_chart.group().all(), function (e) {
1429
+ return _chart.keyAccessor()(e);
1430
+ });
1431
+ return dc.utils.add(max, _xAxisPadding);
1432
+ };
1433
+
1434
+ _chart.yAxisMin = function () {
1435
+ var min = d3.min(_chart.group().all(), function (e) {
1436
+ return _chart.valueAccessor()(e);
1437
+ });
1438
+ min = dc.utils.subtract(min, _yAxisPadding);
1439
+ return min;
1440
+ };
1441
+
1442
+ _chart.yAxisMax = function () {
1443
+ var max = d3.max(_chart.group().all(), function (e) {
1444
+ return _chart.valueAccessor()(e);
1445
+ });
1446
+ max = dc.utils.add(max, _yAxisPadding);
1447
+ return max;
1448
+ };
1449
+
1450
+ _chart.yAxisPadding = function (_) {
1451
+ if (!arguments.length) return _yAxisPadding;
1452
+ _yAxisPadding = _;
1453
+ return _chart;
1454
+ };
1455
+
1456
+ _chart.yAxisHeight = function () {
1457
+ return _chart.effectiveHeight();
1458
+ };
1459
+
1460
+ _chart.round = function (_) {
1461
+ if (!arguments.length) return _round;
1462
+ _round = _;
1463
+ return _chart;
1464
+ };
1465
+
1466
+ dc.override(_chart, "filter", function (_) {
1467
+ if (!arguments.length) return _chart._filter();
1468
+
1469
+ _chart._filter(_);
1470
+
1471
+ if (_) {
1472
+ _chart.brush().extent(_);
1473
+ } else {
1474
+ _chart.brush().clear();
1475
+ }
1476
+
1477
+ return _chart;
1478
+ });
1479
+
1480
+ _chart.brush = function (_) {
1481
+ if (!arguments.length) return _brush;
1482
+ _brush = _;
1483
+ return _chart;
1484
+ };
1485
+
1486
+ function brushHeight() {
1487
+ return _chart.xAxisY() - _chart.margins().top;
1488
+ }
1489
+
1490
+ _chart.renderBrush = function (g) {
1491
+ if (_chart.isOrdinal())
1492
+ _brushOn = false;
1493
+
1494
+ if (_brushOn) {
1495
+ _brush.on("brushstart", brushStart)
1496
+ .on("brush", brushing)
1497
+ .on("brushend", brushEnd);
1498
+
1499
+ var gBrush = g.append("g")
1500
+ .attr("class", "brush")
1501
+ .attr("transform", "translate(" + _chart.margins().left + "," + _chart.margins().top + ")")
1502
+ .call(_brush.x(_chart.x()));
1503
+ gBrush.selectAll("rect").attr("height", brushHeight());
1504
+ gBrush.selectAll(".resize").append("path").attr("d", _chart.resizeHandlePath);
1505
+
1506
+ if (_chart.hasFilter()) {
1507
+ _chart.redrawBrush(g);
1508
+ }
1509
+ }
1510
+ };
1511
+
1512
+ function brushStart(p) {
1513
+ }
1514
+
1515
+ _chart.extendBrush = function () {
1516
+ var extent = _brush.extent();
1517
+ if (_chart.round()) {
1518
+ extent[0] = extent.map(_chart.round())[0];
1519
+ extent[1] = extent.map(_chart.round())[1];
1520
+
1521
+ _g.select(".brush")
1522
+ .call(_brush.extent(extent));
1523
+ }
1524
+ return extent;
1525
+ };
1526
+
1527
+ _chart.brushIsEmpty = function (extent) {
1528
+ return _brush.empty() || !extent || extent[1] <= extent[0];
1529
+ };
1530
+
1531
+ function brushing(p) {
1532
+ var extent = _chart.extendBrush();
1533
+
1534
+ _chart.redrawBrush(_g);
1535
+
1536
+ if (_chart.brushIsEmpty(extent)) {
1537
+ dc.events.trigger(function () {
1538
+ _chart.filter(null);
1539
+ dc.redrawAll(_chart.chartGroup());
1540
+ });
1541
+ } else {
1542
+ dc.events.trigger(function () {
1543
+ _chart.filter(null);
1544
+ _chart.filter([extent[0], extent[1]]);
1545
+ dc.redrawAll(_chart.chartGroup());
1546
+ }, dc.constants.EVENT_DELAY);
1547
+ }
1548
+ }
1549
+
1550
+ function brushEnd(p) {
1551
+ }
1552
+
1553
+ _chart.redrawBrush = function (g) {
1554
+ if (_brushOn) {
1555
+ if (_chart.filter() && _chart.brush().empty())
1556
+ _chart.brush().extent(_chart.filter());
1557
+
1558
+ var gBrush = g.select("g.brush");
1559
+ gBrush.call(_chart.brush().x(_chart.x()));
1560
+ gBrush.selectAll("rect").attr("height", brushHeight());
1561
+ }
1562
+
1563
+ _chart.fadeDeselectedArea();
1564
+ };
1565
+
1566
+ _chart.fadeDeselectedArea = function () {
1567
+ // do nothing, sub-chart should override this function
1568
+ };
1569
+
1570
+ // borrowed from Crossfilter example
1571
+ _chart.resizeHandlePath = function (d) {
1572
+ var e = +(d == "e"), x = e ? 1 : -1, y = brushHeight() / 3;
1573
+ return "M" + (0.5 * x) + "," + y
1574
+ + "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6)
1575
+ + "V" + (2 * y - 6)
1576
+ + "A6,6 0 0 " + e + " " + (0.5 * x) + "," + (2 * y)
1577
+ + "Z"
1578
+ + "M" + (2.5 * x) + "," + (y + 8)
1579
+ + "V" + (2 * y - 8)
1580
+ + "M" + (4.5 * x) + "," + (y + 8)
1581
+ + "V" + (2 * y - 8);
1582
+ };
1583
+
1584
+ function getClipPathId() {
1585
+ return _chart.anchorName() + "-clip";
1586
+ }
1587
+
1588
+ _chart.clipPadding = function (p) {
1589
+ if (!arguments.length) return _clipPadding;
1590
+ _clipPadding = p;
1591
+ return _chart;
1592
+ };
1593
+
1594
+ function generateClipPath() {
1595
+ var defs = dc.utils.appendOrSelect(_parent, "defs");
1596
+
1597
+ var chartBodyClip = dc.utils.appendOrSelect(defs, "clipPath").attr("id", getClipPathId());
1598
+
1599
+ var padding = _clipPadding * 2;
1600
+
1601
+ dc.utils.appendOrSelect(chartBodyClip, "rect")
1602
+ .attr("width", _chart.xAxisLength() + padding)
1603
+ .attr("height", _chart.yAxisHeight() + padding);
1604
+ }
1605
+
1606
+ _chart.doRender = function () {
1607
+ if (_x === undefined)
1608
+ throw new dc.errors.InvalidStateException("Mandatory attribute chart.x is missing on chart[#"
1609
+ + _chart.anchorName() + "]");
1610
+
1611
+ _chart.resetSvg();
1612
+
1613
+ if (_chart.dataSet()) {
1614
+ _chart.generateG();
1615
+
1616
+ generateClipPath();
1617
+ prepareXAxis(_chart.g());
1618
+ prepareYAxis(_chart.g());
1619
+
1620
+ _chart.plotData();
1621
+
1622
+ _chart.renderXAxis(_chart.g());
1623
+ _chart.renderYAxis(_chart.g());
1624
+
1625
+ _chart.renderBrush(_chart.g());
1626
+
1627
+ enableMouseZoom();
1628
+ }
1629
+
1630
+ return _chart;
1631
+ };
1632
+
1633
+ function enableMouseZoom() {
1634
+ if (_mouseZoomable) {
1635
+ _chart.root().call(d3.behavior.zoom()
1636
+ .x(_chart.x())
1637
+ .scaleExtent(_zoomScale)
1638
+ .on("zoom", function () {
1639
+ _chart.focus(_chart.x().domain());
1640
+ _chart.invokeZoomedListener();
1641
+ updateRangeSelChart();
1642
+ }));
1643
+ }
1644
+ }
1645
+
1646
+ function updateRangeSelChart() {
1647
+ if (_rangeChart) {
1648
+ var refDom = _chart.x().domain();
1649
+ if (_zoomOutRestrict) {
1650
+ var origDom = _rangeChart.xOriginalDomain();
1651
+ var newDom = [
1652
+ refDom[0] < origDom[0] ? refDom[0] : origDom[0],
1653
+ refDom[1] > origDom[1] ? refDom[1] : origDom[1]];
1654
+ _rangeChart.focus(newDom);
1655
+ } else {
1656
+ _rangeChart.focus(refDom);
1657
+ }
1658
+ _rangeChart.filter(null);
1659
+ _rangeChart.filter(refDom);
1660
+
1661
+ dc.events.trigger(function () {
1662
+ dc.redrawAll(_chart.chartGroup());
1663
+ });
1664
+ }
1665
+ }
1666
+
1667
+ _chart.doRedraw = function () {
1668
+ prepareXAxis(_chart.g());
1669
+ prepareYAxis(_chart.g());
1670
+
1671
+ _chart.plotData();
1672
+
1673
+ if (_chart.elasticY())
1674
+ _chart.renderYAxis(_chart.g());
1675
+
1676
+ if (_chart.elasticX() || _refocused)
1677
+ _chart.renderXAxis(_chart.g());
1678
+
1679
+ _chart.redrawBrush(_chart.g());
1680
+
1681
+ return _chart;
1682
+ };
1683
+
1684
+ _chart.subRender = function () {
1685
+ if (_chart.dataSet()) {
1686
+ _chart.plotData();
1687
+ }
1688
+
1689
+ return _chart;
1690
+ };
1691
+
1692
+ _chart.brushOn = function (_) {
1693
+ if (!arguments.length) return _brushOn;
1694
+ _brushOn = _;
1695
+ return _chart;
1696
+ };
1697
+
1698
+ _chart.getDataWithinXDomain = function (group) {
1699
+ var data = [];
1700
+
1701
+ if (_chart.isOrdinal()) {
1702
+ data = group.all();
1703
+ } else {
1704
+ group.all().forEach(function (d) {
1705
+ var key = _chart.keyAccessor()(d);
1706
+ if (key >= _chart.x().domain()[0] && key <= _chart.x().domain()[1])
1707
+ data.push(d);
1708
+ });
1709
+ }
1710
+
1711
+ return data;
1712
+ };
1713
+
1714
+ function hasRangeSelected(range) {
1715
+ return range instanceof Array && range.length > 1;
1716
+ }
1717
+
1718
+ _chart.focus = function (range) {
1719
+ _refocused = true;
1720
+
1721
+ if (hasRangeSelected(range)) {
1722
+ _chart.x().domain(range);
1723
+ } else {
1724
+ _chart.x().domain(_chart.xOriginalDomain());
1725
+ }
1726
+
1727
+ _chart.rescale();
1728
+
1729
+ _chart.redraw();
1730
+
1731
+ if (!hasRangeSelected(range))
1732
+ _refocused = false;
1733
+ };
1734
+
1735
+ _chart.refocused = function () {
1736
+ return _refocused;
1737
+ };
1738
+
1739
+ _chart.focusChart = function (c) {
1740
+ if (!arguments.length) return _focusChart;
1741
+ _focusChart = c;
1742
+ _chart.on("filtered", function (chart) {
1743
+ dc.events.trigger(function () {
1744
+ _focusChart.focus(chart.filter());
1745
+ _focusChart.filter(chart.filter());
1746
+ dc.redrawAll(chart.chartGroup());
1747
+ });
1748
+ });
1749
+ return _chart;
1750
+ };
1751
+
1752
+ return _chart;
1753
+ };
1754
+
1755
+ dc.colorChart = function(_chart) {
1756
+ var _colors = d3.scale.category20c();
1757
+
1758
+ var _colorDomain = [0, _colors.range().length];
1759
+
1760
+ var _colorCalculator = function(value) {
1761
+ var minValue = _colorDomain[0];
1762
+ var maxValue = _colorDomain[1];
1763
+
1764
+ if (isNaN(value)) value = 0;
1765
+ if(maxValue === null) return _colors(value);
1766
+
1767
+ var colorsLength = _chart.colors().range().length;
1768
+ var denominator = (maxValue - minValue) / colorsLength;
1769
+ var colorValue = Math.abs(Math.min(colorsLength - 1, Math.round((value - minValue) / denominator)));
1770
+ return _chart.colors()(colorValue);
1771
+ };
1772
+
1773
+ var _colorAccessor = function(d, i){return i;};
1774
+
1775
+ _chart.colors = function(_) {
1776
+ if (!arguments.length) return _colors;
1777
+
1778
+ if (_ instanceof Array) {
1779
+ _colors = d3.scale.ordinal().range(_);
1780
+ var domain = [];
1781
+ for(var i = 0; i < _.length; ++i){
1782
+ domain.push(i);
1783
+ }
1784
+ _colors.domain(domain);
1785
+ } else {
1786
+ _colors = _;
1787
+ }
1788
+
1789
+ _colorDomain = [0, _colors.range().length];
1790
+
1791
+ return _chart;
1792
+ };
1793
+
1794
+ _chart.colorCalculator = function(_){
1795
+ if(!arguments.length) return _colorCalculator;
1796
+ _colorCalculator = _;
1797
+ return _chart;
1798
+ };
1799
+
1800
+ _chart.getColor = function(d, i){
1801
+ return _colorCalculator(_colorAccessor(d, i));
1802
+ };
1803
+
1804
+ _chart.colorAccessor = function(_){
1805
+ if(!arguments.length) return _colorAccessor;
1806
+ _colorAccessor = _;
1807
+ return _chart;
1808
+ };
1809
+
1810
+ _chart.colorDomain = function(_){
1811
+ if(!arguments.length) return _colorDomain;
1812
+ _colorDomain = _;
1813
+ return _chart;
1814
+ };
1815
+
1816
+ return _chart;
1817
+ };
1818
+
1819
+ dc.stackableChart = function (_chart) {
1820
+ var _groupStack = new dc.utils.GroupStack();
1821
+ var _stackLayout = d3.layout.stack()
1822
+ .offset("zero")
1823
+ .order("default")
1824
+ .values(function (d) {
1825
+ return d.points;
1826
+ });
1827
+ var _allGroups;
1828
+ var _allValueAccessors;
1829
+ var _allKeyAccessors;
1830
+ var _stackLayers;
1831
+
1832
+ _chart.stack = function (group, p2, retriever) {
1833
+ if(!arguments.length)
1834
+ _groupStack.clear();
1835
+
1836
+ if (typeof p2 === 'string')
1837
+ _chart.setGroupName(group, p2, retriever);
1838
+ else if (typeof p2 === 'function')
1839
+ retriever = p2;
1840
+
1841
+ _groupStack.setDefaultAccessor(_chart.valueAccessor());
1842
+ _groupStack.addGroup(group, retriever);
1843
+
1844
+ _chart.expireCache();
1845
+
1846
+ return _chart;
1847
+ };
1848
+
1849
+ _chart.expireCache = function () {
1850
+ _allGroups = null;
1851
+ _allValueAccessors = null;
1852
+ _allKeyAccessors = null;
1853
+ _stackLayers = null;
1854
+ return _chart;
1855
+ };
1856
+
1857
+ _chart.allGroups = function () {
1858
+ if (_allGroups === null) {
1859
+ _allGroups = [];
1860
+
1861
+ _allGroups.push(_chart.group());
1862
+
1863
+ for (var i = 0; i < _groupStack.size(); ++i)
1864
+ _allGroups.push(_groupStack.getGroupByIndex(i));
1865
+ }
1866
+
1867
+ return _allGroups;
1868
+ };
1869
+
1870
+ _chart.allValueAccessors = function () {
1871
+ if (_allValueAccessors === null) {
1872
+ _allValueAccessors = [];
1873
+
1874
+ _allValueAccessors.push(_chart.valueAccessor());
1875
+
1876
+ for (var i = 0; i < _groupStack.size(); ++i)
1877
+ _allValueAccessors.push(_groupStack.getAccessorByIndex(i));
1878
+ }
1879
+
1880
+ return _allValueAccessors;
1881
+ };
1882
+
1883
+ _chart.getValueAccessorByIndex = function (groupIndex) {
1884
+ return _chart.allValueAccessors()[groupIndex];
1885
+ };
1886
+
1887
+ _chart.yAxisMin = function () {
1888
+ var min, all = flattenStack();
1889
+
1890
+ min = d3.min(all, function (p) {
1891
+ return (p.y + p.y0 < p.y0) ? (p.y + p.y0) : p.y0;
1892
+ });
1893
+
1894
+ min = dc.utils.subtract(min, _chart.yAxisPadding());
1895
+
1896
+ return min;
1897
+ };
1898
+
1899
+ _chart.yAxisMax = function () {
1900
+ var max, all = flattenStack();
1901
+
1902
+ max = d3.max(all, function (p) {
1903
+ return p.y + p.y0;
1904
+ });
1905
+
1906
+ max = dc.utils.add(max, _chart.yAxisPadding());
1907
+
1908
+ return max;
1909
+ };
1910
+
1911
+ function flattenStack() {
1912
+ var all = [];
1913
+
1914
+ if (_chart.x()) {
1915
+ var xDomain = _chart.x().domain();
1916
+
1917
+ _chart.stackLayers().forEach(function (e) {
1918
+ e.points.forEach(function (p) {
1919
+ if (p.x >= xDomain[0] && p.x <= xDomain[xDomain.length-1])
1920
+ all.push(p);
1921
+ });
1922
+ });
1923
+ } else {
1924
+ _chart.stackLayers().forEach(function (e) {
1925
+ all = all.concat(e.points);
1926
+ });
1927
+ }
1928
+
1929
+ return all;
1930
+ }
1931
+
1932
+ _chart.allKeyAccessors = function () {
1933
+ if (_allKeyAccessors === null) {
1934
+ _allKeyAccessors = [];
1935
+
1936
+ _allKeyAccessors.push(_chart.keyAccessor());
1937
+
1938
+ for (var i = 0; i < _groupStack.size(); ++i)
1939
+ _allKeyAccessors.push(_chart.keyAccessor());
1940
+ }
1941
+
1942
+ return _allKeyAccessors;
1943
+ };
1944
+
1945
+ _chart.getKeyAccessorByIndex = function (groupIndex) {
1946
+ return _chart.allKeyAccessors()[groupIndex];
1947
+ };
1948
+
1949
+ _chart.xAxisMin = function () {
1950
+ var min = null;
1951
+ var allGroups = _chart.allGroups();
1952
+
1953
+ for (var groupIndex = 0; groupIndex < allGroups.length; ++groupIndex) {
1954
+ var group = allGroups[groupIndex];
1955
+ var m = dc.utils.groupMin(group, _chart.getKeyAccessorByIndex(groupIndex));
1956
+ if (min === null || min > m) min = m;
1957
+ }
1958
+
1959
+ return dc.utils.subtract(min, _chart.xAxisPadding());
1960
+ };
1961
+
1962
+ _chart.xAxisMax = function () {
1963
+ var max = null;
1964
+ var allGroups = _chart.allGroups();
1965
+
1966
+ for (var groupIndex = 0; groupIndex < allGroups.length; ++groupIndex) {
1967
+ var group = allGroups[groupIndex];
1968
+ var m = dc.utils.groupMax(group, _chart.getKeyAccessorByIndex(groupIndex));
1969
+ if (max === null || max < m) max = m;
1970
+ }
1971
+
1972
+ return dc.utils.add(max, _chart.xAxisPadding());
1973
+ };
1974
+
1975
+ function getKeyFromData(groupIndex, d) {
1976
+ return _chart.getKeyAccessorByIndex(groupIndex)(d);
1977
+ }
1978
+
1979
+ function getValueFromData(groupIndex, d) {
1980
+ return _chart.getValueAccessorByIndex(groupIndex)(d);
1981
+ }
1982
+
1983
+ function calculateDataPointMatrix(data, groupIndex) {
1984
+ for (var dataIndex = 0; dataIndex < data.length; ++dataIndex) {
1985
+ var d = data[dataIndex];
1986
+ var key = getKeyFromData(groupIndex, d);
1987
+ var value = getValueFromData(groupIndex, d);
1988
+
1989
+ _groupStack.setDataPoint(groupIndex, dataIndex, {data: d, x: key, y: value});
1990
+ }
1991
+ }
1992
+
1993
+ _chart.calculateDataPointMatrixForAll = function () {
1994
+ var groups = _chart.allGroups();
1995
+ for (var groupIndex = 0; groupIndex < groups.length; ++groupIndex) {
1996
+ var group = groups[groupIndex];
1997
+ var data = group.all();
1998
+
1999
+ calculateDataPointMatrix(data, groupIndex);
2000
+ }
2001
+ };
2002
+
2003
+ _chart.getChartStack = function () {
2004
+ return _groupStack;
2005
+ };
2006
+
2007
+ dc.override(_chart, "valueAccessor", function (_) {
2008
+ if (!arguments.length) return _chart._valueAccessor();
2009
+ _chart.expireCache();
2010
+ return _chart._valueAccessor(_);
2011
+ });
2012
+
2013
+ dc.override(_chart, "keyAccessor", function (_) {
2014
+ if (!arguments.length) return _chart._keyAccessor();
2015
+ _chart.expireCache();
2016
+ return _chart._keyAccessor(_);
2017
+ });
2018
+
2019
+ _chart.stackLayout = function (stack) {
2020
+ if (!arguments.length) return _stackLayout;
2021
+ _stackLayout = stack;
2022
+ return _chart;
2023
+ };
2024
+
2025
+ _chart.stackLayers = function (_) {
2026
+ if (!arguments.length) {
2027
+ if (_stackLayers === null) {
2028
+ _chart.calculateDataPointMatrixForAll();
2029
+ _stackLayers = _chart.stackLayout()(_groupStack.toLayers());
2030
+ }
2031
+ return _stackLayers;
2032
+ } else {
2033
+ _stackLayers = _;
2034
+ }
2035
+ };
2036
+
2037
+ _chart.legendables = function () {
2038
+ var items = [];
2039
+ _allGroups.forEach(function (g, i) {
2040
+ items.push(dc.utils.createLegendable(_chart, g, i, _chart.getValueAccessorByIndex(i)));
2041
+ });
2042
+ return items;
2043
+ };
2044
+
2045
+ return _chart;
2046
+ };
2047
+
2048
+ dc.abstractBubbleChart = function (_chart) {
2049
+ var _maxBubbleRelativeSize = 0.3;
2050
+ var _minRadiusWithLabel = 10;
2051
+
2052
+ _chart.BUBBLE_NODE_CLASS = "node";
2053
+ _chart.BUBBLE_CLASS = "bubble";
2054
+ _chart.MIN_RADIUS = 10;
2055
+
2056
+ _chart = dc.colorChart(_chart);
2057
+
2058
+ _chart.renderLabel(true);
2059
+ _chart.renderTitle(false);
2060
+
2061
+ var _r = d3.scale.linear().domain([0, 100]);
2062
+
2063
+ var _rValueAccessor = function (d) {
2064
+ return d.r;
2065
+ };
2066
+
2067
+ _chart.r = function (_) {
2068
+ if (!arguments.length) return _r;
2069
+ _r = _;
2070
+ return _chart;
2071
+ };
2072
+
2073
+ _chart.radiusValueAccessor = function (_) {
2074
+ if (!arguments.length) return _rValueAccessor;
2075
+ _rValueAccessor = _;
2076
+ return _chart;
2077
+ };
2078
+
2079
+ _chart.rMin = function () {
2080
+ var min = d3.min(_chart.group().all(), function (e) {
2081
+ return _chart.radiusValueAccessor()(e);
2082
+ });
2083
+ return min;
2084
+ };
2085
+
2086
+ _chart.rMax = function () {
2087
+ var max = d3.max(_chart.group().all(), function (e) {
2088
+ return _chart.radiusValueAccessor()(e);
2089
+ });
2090
+ return max;
2091
+ };
2092
+
2093
+ _chart.bubbleR = function (d) {
2094
+ var value = _chart.radiusValueAccessor()(d);
2095
+ var r = _chart.r()(value);
2096
+ if (isNaN(r) || value <= 0)
2097
+ r = 0;
2098
+ return r;
2099
+ };
2100
+
2101
+ var labelFunction = function (d) {
2102
+ return _chart.label()(d);
2103
+ };
2104
+
2105
+ var labelOpacity = function (d) {
2106
+ return (_chart.bubbleR(d) > _minRadiusWithLabel) ? 1 : 0;
2107
+ };
2108
+
2109
+ _chart.doRenderLabel = function (bubbleGEnter) {
2110
+ if (_chart.renderLabel()) {
2111
+ var label = bubbleGEnter.select("text");
2112
+
2113
+ if (label.empty()) {
2114
+ label = bubbleGEnter.append("text")
2115
+ .attr("text-anchor", "middle")
2116
+ .attr("dy", ".3em")
2117
+ .on("click", _chart.onClick);
2118
+ }
2119
+
2120
+ label
2121
+ .attr("opacity", 0)
2122
+ .text(labelFunction);
2123
+ dc.transition(label, _chart.transitionDuration())
2124
+ .attr("opacity", labelOpacity);
2125
+ }
2126
+ };
2127
+
2128
+ _chart.doUpdateLabels = function (bubbleGEnter) {
2129
+ if (_chart.renderLabel()) {
2130
+ var labels = bubbleGEnter.selectAll("text")
2131
+ .text(labelFunction);
2132
+ dc.transition(labels, _chart.transitionDuration())
2133
+ .attr("opacity", labelOpacity);
2134
+ }
2135
+ };
2136
+
2137
+ var titleFunction = function (d) {
2138
+ return _chart.title()(d);
2139
+ };
2140
+
2141
+ _chart.doRenderTitles = function (g) {
2142
+ if (_chart.renderTitle()) {
2143
+ var title = g.select("title");
2144
+
2145
+ if (title.empty())
2146
+ g.append("title").text(titleFunction);
2147
+ }
2148
+ };
2149
+
2150
+ _chart.doUpdateTitles = function (g) {
2151
+ if (_chart.renderTitle()) {
2152
+ g.selectAll("title").text(titleFunction);
2153
+ }
2154
+ };
2155
+
2156
+ _chart.minRadiusWithLabel = function (_) {
2157
+ if (!arguments.length) return _minRadiusWithLabel;
2158
+ _minRadiusWithLabel = _;
2159
+ return _chart;
2160
+ };
2161
+
2162
+ _chart.maxBubbleRelativeSize = function (_) {
2163
+ if (!arguments.length) return _maxBubbleRelativeSize;
2164
+ _maxBubbleRelativeSize = _;
2165
+ return _chart;
2166
+ };
2167
+
2168
+ _chart.initBubbleColor = function (d, i) {
2169
+ this[dc.constants.NODE_INDEX_NAME] = i;
2170
+ return _chart.getColor(d, i);
2171
+ };
2172
+
2173
+ _chart.updateBubbleColor = function (d, i) {
2174
+ // a work around to get correct node index since
2175
+ return _chart.getColor(d, this[dc.constants.NODE_INDEX_NAME]);
2176
+ };
2177
+
2178
+ _chart.fadeDeselectedArea = function () {
2179
+ if (_chart.hasFilter()) {
2180
+ _chart.selectAll("g." + _chart.BUBBLE_NODE_CLASS).each(function (d) {
2181
+ if (_chart.isSelectedNode(d)) {
2182
+ _chart.highlightSelected(this);
2183
+ } else {
2184
+ _chart.fadeDeselected(this);
2185
+ }
2186
+ });
2187
+ } else {
2188
+ _chart.selectAll("g." + _chart.BUBBLE_NODE_CLASS).each(function (d) {
2189
+ _chart.resetHighlight(this);
2190
+ });
2191
+ }
2192
+ };
2193
+
2194
+ _chart.isSelectedNode = function (d) {
2195
+ return _chart.hasFilter(d.key);
2196
+ };
2197
+
2198
+ _chart.onClick = function (d) {
2199
+ var filter = d.key;
2200
+ dc.events.trigger(function () {
2201
+ _chart.filter(filter);
2202
+ dc.redrawAll(_chart.chartGroup());
2203
+ });
2204
+ };
2205
+
2206
+ return _chart;
2207
+ };
2208
+
2209
+ dc.pieChart = function (parent, chartGroup) {
2210
+ var DEFAULT_MIN_ANGLE_FOR_LABEL = 0.5;
2211
+
2212
+ var _sliceCssClass = "pie-slice";
2213
+
2214
+ var _radius,
2215
+ _innerRadius = 0;
2216
+
2217
+ var _g;
2218
+
2219
+ var _minAngleForLabel = DEFAULT_MIN_ANGLE_FOR_LABEL;
2220
+
2221
+ var _chart = dc.colorChart(dc.baseChart({}));
2222
+
2223
+ var _slicesCap = Infinity;
2224
+ var _othersLabel = "Others";
2225
+ var _othersGrouper = function (topRows) {
2226
+ var topRowsSum = d3.sum(topRows, _chart.valueAccessor()),
2227
+ allRows = _chart.group().all(),
2228
+ allRowsSum = d3.sum(allRows, _chart.valueAccessor()),
2229
+ topKeys = topRows.map(_chart.keyAccessor()),
2230
+ allKeys = allRows.map(_chart.keyAccessor()),
2231
+ topSet = d3.set(topKeys),
2232
+ others = allKeys.filter(function(d){return !topSet.has(d);});
2233
+ topRows.push({"others": others,"key": _othersLabel, "value": allRowsSum - topRowsSum });
2234
+ };
2235
+
2236
+ function assemblePieData() {
2237
+ if (_slicesCap == Infinity) {
2238
+ return _chart.computeOrderedGroups();
2239
+ } else {
2240
+ var topRows = _chart.group().top(_slicesCap); // ordered by value
2241
+ topRows = _chart.computeOrderedGroups(topRows); // re-order by key
2242
+ _othersGrouper(topRows);
2243
+ return topRows;
2244
+ }
2245
+ }
2246
+
2247
+ _chart.label(function (d) {
2248
+ return _chart.keyAccessor()(d.data);
2249
+ });
2250
+
2251
+ _chart.renderLabel(true);
2252
+
2253
+ _chart.title(function (d) {
2254
+ return _chart.keyAccessor()(d.data) + ": " + _chart.valueAccessor()(d.data);
2255
+ });
2256
+
2257
+ _chart.transitionDuration(350);
2258
+
2259
+ _chart.doRender = function () {
2260
+ _chart.resetSvg();
2261
+
2262
+ _g = _chart.svg()
2263
+ .append("g")
2264
+ .attr("transform", "translate(" + _chart.cx() + "," + _chart.cy() + ")");
2265
+
2266
+ drawChart();
2267
+
2268
+ return _chart;
2269
+ };
2270
+
2271
+ function drawChart() {
2272
+ if (_chart.dataSet()) {
2273
+ var pie = calculateDataPie();
2274
+
2275
+ // set radius on basis of chart dimension if missing
2276
+ _radius = _radius ? _radius : d3.min([_chart.width(), _chart.height()]) /2;
2277
+
2278
+ var arc = _chart.buildArcs();
2279
+
2280
+ var pieData = pie(assemblePieData());
2281
+
2282
+ if (_g) {
2283
+ var slices = _g.selectAll("g." + _sliceCssClass)
2284
+ .data(pieData);
2285
+
2286
+ createElements(slices, arc, pieData);
2287
+
2288
+ updateElements(pieData, arc);
2289
+
2290
+ removeElements(slices);
2291
+
2292
+ highlightFilter();
2293
+ }
2294
+ }
2295
+ }
2296
+
2297
+ function createElements(slices, arc, pieData) {
2298
+ var slicesEnter = createSliceNodes(slices);
2299
+
2300
+ createSlicePath(slicesEnter, arc);
2301
+
2302
+ createTitles(slicesEnter);
2303
+
2304
+ createLabels(pieData, arc);
2305
+ }
2306
+
2307
+ function createSliceNodes(slices) {
2308
+ var slicesEnter = slices
2309
+ .enter()
2310
+ .append("g")
2311
+ .attr("class", function (d, i) {
2312
+ return _sliceCssClass + " _" + i;
2313
+ });
2314
+ return slicesEnter;
2315
+ }
2316
+
2317
+ function createSlicePath(slicesEnter, arc) {
2318
+ var slicePath = slicesEnter.append("path")
2319
+ .attr("fill", function (d, i) {
2320
+ return _chart.getColor(d, i);
2321
+ })
2322
+ .on("click", onClick)
2323
+ .attr("d", function (d, i) {
2324
+ return safeArc(d, i, arc);
2325
+ });
2326
+ slicePath.transition()
2327
+ .duration(_chart.transitionDuration())
2328
+ .attrTween("d", tweenPie);
2329
+ }
2330
+
2331
+ function createTitles(slicesEnter) {
2332
+ if (_chart.renderTitle()) {
2333
+ slicesEnter.append("title").text(function (d) {
2334
+ return _chart.title()(d);
2335
+ });
2336
+ }
2337
+ }
2338
+
2339
+ function createLabels(pieData, arc) {
2340
+ if (_chart.renderLabel()) {
2341
+ var labels = _g.selectAll("text." + _sliceCssClass)
2342
+ .data(pieData);
2343
+
2344
+ labels.exit().remove();
2345
+
2346
+ var labelsEnter = labels
2347
+ .enter()
2348
+ .append("text")
2349
+ .attr("class", function (d, i) {
2350
+ return _sliceCssClass + " _" + i;
2351
+ })
2352
+ .on("click", onClick);
2353
+ dc.transition(labelsEnter, _chart.transitionDuration())
2354
+ .attr("transform", function (d) {
2355
+ d.innerRadius = _chart.innerRadius();
2356
+ d.outerRadius = _radius;
2357
+ var centroid = arc.centroid(d);
2358
+ if (isNaN(centroid[0]) || isNaN(centroid[1])) {
2359
+ return "translate(0,0)";
2360
+ } else {
2361
+ return "translate(" + centroid + ")";
2362
+ }
2363
+ })
2364
+ .attr("text-anchor", "middle")
2365
+ .text(function (d) {
2366
+ var data = d.data;
2367
+ if (sliceHasNoData(data) || sliceTooSmall(d))
2368
+ return "";
2369
+ return _chart.label()(d);
2370
+ });
2371
+ }
2372
+ }
2373
+
2374
+ function updateElements(pieData, arc) {
2375
+ updateSlicePaths(pieData, arc);
2376
+ updateLabels(pieData, arc);
2377
+ updateTitles(pieData);
2378
+ }
2379
+
2380
+ function updateSlicePaths(pieData, arc) {
2381
+ var slicePaths = _g.selectAll("g." + _sliceCssClass)
2382
+ .data(pieData)
2383
+ .select("path")
2384
+ .attr("d", function (d, i) {
2385
+ return safeArc(d, i, arc);
2386
+ });
2387
+ dc.transition(slicePaths, _chart.transitionDuration(),
2388
+ function (s) {
2389
+ s.attrTween("d", tweenPie);
2390
+ }).attr("fill", function (d, i) {
2391
+ return _chart.getColor(d, i);
2392
+ });
2393
+ }
2394
+
2395
+ function updateLabels(pieData, arc) {
2396
+ if (_chart.renderLabel()) {
2397
+ var labels = _g.selectAll("text." + _sliceCssClass)
2398
+ .data(pieData);
2399
+ dc.transition(labels, _chart.transitionDuration())
2400
+ .attr("transform", function (d) {
2401
+ d.innerRadius = _chart.innerRadius();
2402
+ d.outerRadius = _radius;
2403
+ var centroid = arc.centroid(d);
2404
+ if (isNaN(centroid[0]) || isNaN(centroid[1])) {
2405
+ return "translate(0,0)";
2406
+ } else {
2407
+ return "translate(" + centroid + ")";
2408
+ }
2409
+ })
2410
+ .attr("text-anchor", "middle")
2411
+ .text(function (d) {
2412
+ var data = d.data;
2413
+ if (sliceHasNoData(data) || sliceTooSmall(d))
2414
+ return "";
2415
+ return _chart.label()(d);
2416
+ });
2417
+ }
2418
+ }
2419
+
2420
+ function updateTitles(pieData) {
2421
+ if (_chart.renderTitle()) {
2422
+ _g.selectAll("g." + _sliceCssClass)
2423
+ .data(pieData)
2424
+ .select("title")
2425
+ .text(function (d) {
2426
+ return _chart.title()(d);
2427
+ });
2428
+ }
2429
+ }
2430
+
2431
+ function removeElements(slices) {
2432
+ slices.exit().remove();
2433
+ }
2434
+
2435
+ function highlightFilter() {
2436
+ if (_chart.hasFilter()) {
2437
+ _chart.selectAll("g." + _sliceCssClass).each(function (d) {
2438
+ if (_chart.isSelectedSlice(d)) {
2439
+ _chart.highlightSelected(this);
2440
+ } else {
2441
+ _chart.fadeDeselected(this);
2442
+ }
2443
+ });
2444
+ } else {
2445
+ _chart.selectAll("g." + _sliceCssClass).each(function (d) {
2446
+ _chart.resetHighlight(this);
2447
+ });
2448
+ }
2449
+ }
2450
+
2451
+ _chart.innerRadius = function (r) {
2452
+ if (!arguments.length) return _innerRadius;
2453
+ _innerRadius = r;
2454
+ return _chart;
2455
+ };
2456
+
2457
+ _chart.radius = function (r) {
2458
+ if (!arguments.length) return _radius;
2459
+ _radius = r;
2460
+ return _chart;
2461
+ };
2462
+
2463
+ _chart.cx = function () {
2464
+ return _chart.width() / 2;
2465
+ };
2466
+
2467
+ _chart.cy = function () {
2468
+ return _chart.height() / 2;
2469
+ };
2470
+
2471
+ _chart.buildArcs = function () {
2472
+ return d3.svg.arc().outerRadius(_radius).innerRadius(_innerRadius);
2473
+ };
2474
+
2475
+ _chart.isSelectedSlice = function (d) {
2476
+ return _chart.hasFilter(_chart.keyAccessor()(d.data));
2477
+ };
2478
+
2479
+ _chart.doRedraw = function () {
2480
+ drawChart();
2481
+ return _chart;
2482
+ };
2483
+
2484
+ _chart.minAngleForLabel = function (_) {
2485
+ if (!arguments.length) return _minAngleForLabel;
2486
+ _minAngleForLabel = _;
2487
+ return _chart;
2488
+ };
2489
+
2490
+ _chart.slicesCap = function (_) {
2491
+ if (!arguments.length) return _slicesCap;
2492
+ _slicesCap = _;
2493
+ return _chart;
2494
+ };
2495
+
2496
+ _chart.othersLabel = function (_) {
2497
+ if (!arguments.length) return _othersLabel;
2498
+ _othersLabel = _;
2499
+ return _chart;
2500
+ };
2501
+
2502
+ _chart.othersGrouper = function (_) {
2503
+ if (!arguments.length) return _othersGrouper;
2504
+ _othersGrouper = _;
2505
+ return _chart;
2506
+ };
2507
+
2508
+ function calculateDataPie() {
2509
+ return d3.layout.pie().sort(null).value(function (d) {
2510
+ return _chart.valueAccessor()(d);
2511
+ });
2512
+ }
2513
+
2514
+ function sliceTooSmall(d) {
2515
+ var angle = (d.endAngle - d.startAngle);
2516
+ return isNaN(angle) || angle < _minAngleForLabel;
2517
+ }
2518
+
2519
+ function sliceHasNoData(data) {
2520
+ return _chart.valueAccessor()(data) === 0;
2521
+ }
2522
+
2523
+ function tweenPie(b) {
2524
+ b.innerRadius = _chart.innerRadius();
2525
+ var current = this._current;
2526
+ if (isOffCanvas(current))
2527
+ current = {startAngle: 0, endAngle: 0};
2528
+ var i = d3.interpolate(current, b);
2529
+ this._current = i(0);
2530
+ return function (t) {
2531
+ return safeArc(i(t), 0, _chart.buildArcs());
2532
+ };
2533
+ }
2534
+
2535
+ function isOffCanvas(current) {
2536
+ return !current || isNaN(current.startAngle) || isNaN(current.endAngle);
2537
+ }
2538
+
2539
+ function onClick(d) {
2540
+ if (d.data.others)
2541
+ d.data.others.forEach(function(f) {
2542
+ _chart.filter(f);
2543
+ });
2544
+ _chart.onClick(d.data);
2545
+ }
2546
+
2547
+ function safeArc(d, i, arc) {
2548
+ var path = arc(d, i);
2549
+ if (path.indexOf("NaN") >= 0)
2550
+ path = "M0,0";
2551
+ return path;
2552
+ }
2553
+
2554
+ return _chart.anchor(parent, chartGroup);
2555
+ };
2556
+
2557
+ dc.barChart = function (parent, chartGroup) {
2558
+ var MIN_BAR_WIDTH = 1;
2559
+ var DEFAULT_GAP_BETWEEN_BARS = 2;
2560
+
2561
+ var _chart = dc.stackableChart(dc.coordinateGridChart({}));
2562
+
2563
+ var _gap = DEFAULT_GAP_BETWEEN_BARS;
2564
+ var _centerBar = false;
2565
+
2566
+ var _numberOfBars;
2567
+ var _barWidth;
2568
+
2569
+ dc.override(_chart, 'rescale', function () {
2570
+ _chart._rescale();
2571
+ _numberOfBars = undefined;
2572
+ _barWidth = undefined;
2573
+ getNumberOfBars();
2574
+ });
2575
+
2576
+ _chart.plotData = function () {
2577
+ var layers = _chart.chartBodyG().selectAll("g.stack")
2578
+ .data(_chart.stackLayers());
2579
+
2580
+ calculateBarWidth();
2581
+
2582
+ layers
2583
+ .enter()
2584
+ .append("g")
2585
+ .attr("class", function (d, i) {
2586
+ return "stack " + "_" + i;
2587
+ });
2588
+
2589
+ layers.each(function (d, i) {
2590
+ var layer = d3.select(this);
2591
+
2592
+ renderBars(layer, d, i);
2593
+ });
2594
+
2595
+ _chart.stackLayers(null);
2596
+ };
2597
+
2598
+ function barHeight(d) {
2599
+ return dc.utils.safeNumber(Math.abs(_chart.y()(d.y + d.y0) - _chart.y()(d.y0)));
2600
+ }
2601
+
2602
+ function renderBars(layer, d, i) {
2603
+ var bars = layer.selectAll("rect.bar")
2604
+ .data(d.points);
2605
+
2606
+ bars.enter()
2607
+ .append("rect")
2608
+ .attr("class", "bar")
2609
+ .attr("fill", function (d) {
2610
+ return _chart.colors()(i);
2611
+ })
2612
+ .append("title").text(_chart.title());
2613
+
2614
+ if (_chart.isOrdinal())
2615
+ bars.on("click", onClick);
2616
+
2617
+ dc.transition(bars, _chart.transitionDuration())
2618
+ .attr("x", function (d) {
2619
+ var x = _chart.x()(d.x);
2620
+ if (_centerBar || _chart.isOrdinal()) x -= _barWidth / 2;
2621
+ return dc.utils.safeNumber(x);
2622
+ })
2623
+ .attr("y", function (d) {
2624
+ var y = _chart.y()(d.y + d.y0);
2625
+
2626
+ if (d.y < 0)
2627
+ y -= barHeight(d);
2628
+
2629
+ return dc.utils.safeNumber(y);
2630
+ })
2631
+ .attr("width", _barWidth)
2632
+ .attr("height", function (d) {
2633
+ return barHeight(d);
2634
+ })
2635
+ .select("title").text(_chart.title());
2636
+
2637
+ dc.transition(bars.exit(), _chart.transitionDuration())
2638
+ .attr("height", 0)
2639
+ .remove();
2640
+ }
2641
+
2642
+ function calculateBarWidth() {
2643
+ if (_barWidth === undefined) {
2644
+ var numberOfBars = _chart.isOrdinal() ? getNumberOfBars() + 1 : getNumberOfBars();
2645
+
2646
+ var w = Math.floor((_chart.xAxisLength() - (numberOfBars - 1) * _gap) / numberOfBars);
2647
+
2648
+ if (w == Infinity || isNaN(w) || w < MIN_BAR_WIDTH)
2649
+ w = MIN_BAR_WIDTH;
2650
+
2651
+ _barWidth = w;
2652
+ }
2653
+ }
2654
+
2655
+ function getNumberOfBars() {
2656
+ if (_numberOfBars === undefined) {
2657
+ _numberOfBars = _chart.xUnitCount();
2658
+ }
2659
+
2660
+ return _numberOfBars;
2661
+ }
2662
+
2663
+ _chart.fadeDeselectedArea = function () {
2664
+ var bars = _chart.chartBodyG().selectAll("rect.bar");
2665
+ var extent = _chart.brush().extent();
2666
+
2667
+ if (_chart.isOrdinal()) {
2668
+ if (_chart.hasFilter()) {
2669
+ bars.classed(dc.constants.SELECTED_CLASS, function (d) {
2670
+ return _chart.hasFilter(_chart.keyAccessor()(d.data));
2671
+ });
2672
+ bars.classed(dc.constants.DESELECTED_CLASS, function (d) {
2673
+ return !_chart.hasFilter(_chart.keyAccessor()(d.data));
2674
+ });
2675
+ } else {
2676
+ bars.classed(dc.constants.SELECTED_CLASS, false);
2677
+ bars.classed(dc.constants.DESELECTED_CLASS, false);
2678
+ }
2679
+ } else {
2680
+ if (!_chart.brushIsEmpty(extent)) {
2681
+ var start = extent[0];
2682
+ var end = extent[1];
2683
+
2684
+ bars.classed(dc.constants.DESELECTED_CLASS, function (d) {
2685
+ var xValue = _chart.keyAccessor()(d.data);
2686
+ return xValue < start || xValue >= end;
2687
+ });
2688
+ } else {
2689
+ bars.classed(dc.constants.DESELECTED_CLASS, false);
2690
+ }
2691
+ }
2692
+ };
2693
+
2694
+ _chart.centerBar = function (_) {
2695
+ if (!arguments.length) return _centerBar;
2696
+ _centerBar = _;
2697
+ return _chart;
2698
+ };
2699
+
2700
+ function onClick(d) {
2701
+ _chart.onClick(d.data);
2702
+ }
2703
+
2704
+ _chart.gap = function (_) {
2705
+ if (!arguments.length) return _gap;
2706
+ _gap = _;
2707
+ return _chart;
2708
+ };
2709
+
2710
+ _chart.extendBrush = function () {
2711
+ var extent = _chart.brush().extent();
2712
+ if (_chart.round() && !_centerBar) {
2713
+ extent[0] = extent.map(_chart.round())[0];
2714
+ extent[1] = extent.map(_chart.round())[1];
2715
+
2716
+ _chart.chartBodyG().select(".brush")
2717
+ .call(_chart.brush().extent(extent));
2718
+ }
2719
+ return extent;
2720
+ };
2721
+
2722
+ _chart.legendHighlight = function (d) {
2723
+ _chart.select('.chart-body').selectAll('rect.bar').filter(function () {
2724
+ return d3.select(this).attr('fill') == d.color;
2725
+ }).classed('highlight', true);
2726
+ _chart.select('.chart-body').selectAll('rect.bar').filter(function () {
2727
+ return d3.select(this).attr('fill') != d.color;
2728
+ }).classed('fadeout', true);
2729
+ };
2730
+
2731
+ _chart.legendReset = function (d) {
2732
+ _chart.selectAll('.chart-body').selectAll('rect.bar').filter(function () {
2733
+ return d3.select(this).attr('fill') == d.color;
2734
+ }).classed('highlight', false);
2735
+ _chart.selectAll('.chart-body').selectAll('rect.bar').filter(function () {
2736
+ return d3.select(this).attr('fill') != d.color;
2737
+ }).classed('fadeout', false);
2738
+ };
2739
+
2740
+ return _chart.anchor(parent, chartGroup);
2741
+ };
2742
+
2743
+ dc.lineChart = function (parent, chartGroup) {
2744
+ var DEFAULT_DOT_RADIUS = 5;
2745
+ var TOOLTIP_G_CLASS = "dc-tooltip";
2746
+ var DOT_CIRCLE_CLASS = "dot";
2747
+ var Y_AXIS_REF_LINE_CLASS = "yRef";
2748
+ var X_AXIS_REF_LINE_CLASS = "xRef";
2749
+
2750
+ var _chart = dc.stackableChart(dc.coordinateGridChart({}));
2751
+ var _renderArea = false;
2752
+ var _dotRadius = DEFAULT_DOT_RADIUS;
2753
+ var _interpolate = 'linear';
2754
+ var _tension = 0.7;
2755
+
2756
+ _chart.transitionDuration(500);
2757
+
2758
+ _chart.plotData = function () {
2759
+ var layers = _chart.chartBodyG().selectAll("g.stack")
2760
+ .data(_chart.stackLayers());
2761
+
2762
+ var layersEnter = layers
2763
+ .enter()
2764
+ .append("g")
2765
+ .attr("class", function (d, i) {
2766
+ return "stack " + "_" + i;
2767
+ });
2768
+
2769
+ drawLine(layersEnter, layers);
2770
+
2771
+ drawArea(layersEnter, layers);
2772
+
2773
+ drawDots(layers);
2774
+
2775
+ _chart.stackLayers(null);
2776
+ };
2777
+
2778
+ _chart.interpolate = function(_){
2779
+ if (!arguments.length) return _interpolate;
2780
+ _interpolate = _;
2781
+ return _chart;
2782
+ };
2783
+
2784
+ _chart.tension = function(_){
2785
+ if (!arguments.length) return _tension;
2786
+ _tension = _;
2787
+ return _chart;
2788
+ };
2789
+
2790
+ _chart.renderArea = function (_) {
2791
+ if (!arguments.length) return _renderArea;
2792
+ _renderArea = _;
2793
+ return _chart;
2794
+ };
2795
+
2796
+ function drawLine(layersEnter, layers) {
2797
+ var line = d3.svg.line()
2798
+ .x(function (d) {
2799
+ return _chart.x()(d.x);
2800
+ })
2801
+ .y(function (d) {
2802
+ return _chart.y()(d.y + d.y0);
2803
+ })
2804
+ .interpolate(_interpolate)
2805
+ .tension(_tension);
2806
+
2807
+ layersEnter.append("path")
2808
+ .attr("class", "line")
2809
+ .attr("stroke", function (d, i) {
2810
+ return _chart.colors()(i);
2811
+ })
2812
+ .attr("fill", function (d, i) {
2813
+ return _chart.colors()(i);
2814
+ });
2815
+
2816
+ dc.transition(layers.select("path.line"), _chart.transitionDuration())
2817
+ .attr("d", function (d) {
2818
+ return safeD(line(d.points));
2819
+ });
2820
+ }
2821
+
2822
+ function drawArea(layersEnter, layers) {
2823
+ if (_renderArea) {
2824
+ var area = d3.svg.area()
2825
+ .x(function (d) {
2826
+ return _chart.x()(d.x);
2827
+ })
2828
+ .y(function (d) {
2829
+ return _chart.y()(d.y + d.y0);
2830
+ })
2831
+ .y0(function (d) {
2832
+ return _chart.y()(d.y0);
2833
+ })
2834
+ .interpolate(_interpolate)
2835
+ .tension(_tension);
2836
+
2837
+ layersEnter.append("path")
2838
+ .attr("class", "area")
2839
+ .attr("fill", function (d, i) {
2840
+ return _chart.colors()(i);
2841
+ })
2842
+ .attr("d", function (d) {
2843
+ return safeD(area(d.points));
2844
+ });
2845
+
2846
+ dc.transition(layers.select("path.area"), _chart.transitionDuration())
2847
+ .attr("d", function (d) {
2848
+ return safeD(area(d.points));
2849
+ });
2850
+ }
2851
+ }
2852
+
2853
+ function safeD(d){
2854
+ return (!d || d.indexOf("NaN") >= 0) ? "M0,0" : d;
2855
+ }
2856
+
2857
+ function drawDots(layersEnter) {
2858
+ if (!_chart.brushOn()) {
2859
+ layersEnter.each(function (d, i) {
2860
+ var layer = d3.select(this);
2861
+
2862
+ var g = layer.select("g." + TOOLTIP_G_CLASS);
2863
+ if (g.empty()) g = layer.append("g").attr("class", TOOLTIP_G_CLASS);
2864
+
2865
+ createRefLines(g);
2866
+
2867
+ var dots = g.selectAll("circle." + DOT_CIRCLE_CLASS)
2868
+ .data(g.datum().points);
2869
+
2870
+ dots.enter()
2871
+ .append("circle")
2872
+ .attr("class", DOT_CIRCLE_CLASS)
2873
+ .attr("r", _dotRadius)
2874
+ .attr("fill", function (d) {
2875
+ return _chart.colors()(i);
2876
+ })
2877
+ .style("fill-opacity", 1e-6)
2878
+ .style("stroke-opacity", 1e-6)
2879
+ .on("mousemove", function (d) {
2880
+ var dot = d3.select(this);
2881
+ showDot(dot);
2882
+ showRefLines(dot, g);
2883
+ })
2884
+ .on("mouseout", function (d) {
2885
+ var dot = d3.select(this);
2886
+ hideDot(dot);
2887
+ hideRefLines(g);
2888
+ })
2889
+ .append("title").text(_chart.title());
2890
+
2891
+ dots.attr("cx", function (d) {
2892
+ return dc.utils.safeNumber(_chart.x()(d.x));
2893
+ })
2894
+ .attr("cy", function (d) {
2895
+ return dc.utils.safeNumber(_chart.y()(d.y + d.y0));
2896
+ })
2897
+ .select("title").text(_chart.title());
2898
+
2899
+ dots.exit().remove();
2900
+ });
2901
+ }
2902
+ }
2903
+
2904
+ function createRefLines(g) {
2905
+ var yRefLine = g.select("path." + Y_AXIS_REF_LINE_CLASS).empty() ? g.append("path").attr("class", Y_AXIS_REF_LINE_CLASS) : g.select("path." + Y_AXIS_REF_LINE_CLASS);
2906
+ yRefLine.style("display", "none").attr("stroke-dasharray", "5,5");
2907
+
2908
+ var xRefLine = g.select("path." + X_AXIS_REF_LINE_CLASS).empty() ? g.append("path").attr("class", X_AXIS_REF_LINE_CLASS) : g.select("path." + X_AXIS_REF_LINE_CLASS);
2909
+ xRefLine.style("display", "none").attr("stroke-dasharray", "5,5");
2910
+ }
2911
+
2912
+ function showDot(dot) {
2913
+ dot.style("fill-opacity", 0.8);
2914
+ dot.style("stroke-opacity", 0.8);
2915
+ return dot;
2916
+ }
2917
+
2918
+ function showRefLines(dot, g) {
2919
+ var x = dot.attr("cx");
2920
+ var y = dot.attr("cy");
2921
+ g.select("path." + Y_AXIS_REF_LINE_CLASS).style("display", "").attr("d", "M0 " + y + "L" + (x) + " " + (y));
2922
+ g.select("path." + X_AXIS_REF_LINE_CLASS).style("display", "").attr("d", "M" + x + " " + _chart.yAxisHeight() + "L" + x + " " + y);
2923
+ }
2924
+
2925
+ function hideDot(dot) {
2926
+ dot.style("fill-opacity", 1e-6).style("stroke-opacity", 1e-6);
2927
+ }
2928
+
2929
+ function hideRefLines(g) {
2930
+ g.select("path." + Y_AXIS_REF_LINE_CLASS).style("display", "none");
2931
+ g.select("path." + X_AXIS_REF_LINE_CLASS).style("display", "none");
2932
+ }
2933
+
2934
+ _chart.dotRadius = function (_) {
2935
+ if (!arguments.length) return _dotRadius;
2936
+ _dotRadius = _;
2937
+ return _chart;
2938
+ };
2939
+
2940
+ _chart.legendHighlight = function (d) {
2941
+ _chart.selectAll('.chart-body').selectAll('path').filter(function () {
2942
+ return d3.select(this).attr('fill') == d.color;
2943
+ }).classed('highlight', true);
2944
+ _chart.selectAll('.chart-body').selectAll('path').filter(function () {
2945
+ return d3.select(this).attr('fill') != d.color;
2946
+ }).classed('fadeout', true);
2947
+ };
2948
+
2949
+ _chart.legendReset = function (d) {
2950
+ _chart.selectAll('.chart-body').selectAll('path').filter(function () {
2951
+ return d3.select(this).attr('fill') == d.color;
2952
+ }).classed('highlight', false);
2953
+ _chart.selectAll('.chart-body').selectAll('path').filter(function () {
2954
+ return d3.select(this).attr('fill') != d.color;
2955
+ }).classed('fadeout', false);
2956
+ };
2957
+
2958
+ return _chart.anchor(parent, chartGroup);
2959
+ };
2960
+
2961
+ dc.dataCount = function(parent, chartGroup) {
2962
+ var _formatNumber = d3.format(",d");
2963
+ var _chart = dc.baseChart({});
2964
+
2965
+ _chart.doRender = function() {
2966
+ _chart.selectAll(".total-count").text(_formatNumber(_chart.dimension().size()));
2967
+ _chart.selectAll(".filter-count").text(_formatNumber(_chart.group().value()));
2968
+
2969
+ return _chart;
2970
+ };
2971
+
2972
+ _chart.doRedraw = function(){
2973
+ return _chart.doRender();
2974
+ };
2975
+
2976
+ return _chart.anchor(parent, chartGroup);
2977
+ };
2978
+
2979
+ dc.dataTable = function(parent, chartGroup) {
2980
+ var LABEL_CSS_CLASS = "dc-table-label";
2981
+ var ROW_CSS_CLASS = "dc-table-row";
2982
+ var COLUMN_CSS_CLASS = "dc-table-column";
2983
+ var GROUP_CSS_CLASS = "dc-table-group";
2984
+
2985
+ var _chart = dc.baseChart({});
2986
+
2987
+ var _size = 25;
2988
+ var _columns = [];
2989
+ var _sortBy = function(d) {
2990
+ return d;
2991
+ };
2992
+ var _order = d3.ascending;
2993
+ var _sort;
2994
+
2995
+ _chart.doRender = function() {
2996
+ _chart.selectAll("tbody").remove();
2997
+
2998
+ renderRows(renderGroups());
2999
+
3000
+ return _chart;
3001
+ };
3002
+
3003
+ function renderGroups() {
3004
+ var groups = _chart.root().selectAll("tbody")
3005
+ .data(nestEntries(), function(d) {
3006
+ return _chart.keyAccessor()(d);
3007
+ });
3008
+
3009
+ var rowGroup = groups
3010
+ .enter()
3011
+ .append("tbody");
3012
+
3013
+ rowGroup
3014
+ .append("tr")
3015
+ .attr("class", GROUP_CSS_CLASS)
3016
+ .append("td")
3017
+ .attr("class", LABEL_CSS_CLASS)
3018
+ .attr("colspan", _columns.length)
3019
+ .html(function(d) {
3020
+ return _chart.keyAccessor()(d);
3021
+ });
3022
+
3023
+ groups.exit().remove();
3024
+
3025
+ return rowGroup;
3026
+ }
3027
+
3028
+ function nestEntries() {
3029
+ if (!_sort)
3030
+ _sort = crossfilter.quicksort.by(_sortBy);
3031
+
3032
+ var entries = _chart.dimension().top(_size);
3033
+
3034
+ return d3.nest()
3035
+ .key(_chart.group())
3036
+ .sortKeys(_order)
3037
+ .sortValues(_order)
3038
+ .entries(_sort(entries, 0, entries.length));
3039
+ }
3040
+
3041
+ function renderRows(groups) {
3042
+ var rows = groups.order()
3043
+ .selectAll("tr." + ROW_CSS_CLASS)
3044
+ .data(function(d) {
3045
+ return d.values;
3046
+ });
3047
+
3048
+ var rowEnter = rows.enter()
3049
+ .append("tr")
3050
+ .attr("class", ROW_CSS_CLASS);
3051
+
3052
+ for (var i = 0; i < _columns.length; ++i) {
3053
+ var f = _columns[i];
3054
+ rowEnter.append("td")
3055
+ .attr("class", COLUMN_CSS_CLASS + " _" + i)
3056
+ .html(function(d) {
3057
+ return f(d);
3058
+ });
3059
+ }
3060
+
3061
+ rows.exit().remove();
3062
+
3063
+ return rows;
3064
+ }
3065
+
3066
+ _chart.doRedraw = function() {
3067
+ return _chart.doRender();
3068
+ };
3069
+
3070
+ _chart.size = function(s) {
3071
+ if (!arguments.length) return _size;
3072
+ _size = s;
3073
+ return _chart;
3074
+ };
3075
+
3076
+ _chart.columns = function(_) {
3077
+ if (!arguments.length) return _columns;
3078
+ _columns = _;
3079
+ return _chart;
3080
+ };
3081
+
3082
+ _chart.sortBy = function(_) {
3083
+ if (!arguments.length) return _sortBy;
3084
+ _sortBy = _;
3085
+ return _chart;
3086
+ };
3087
+
3088
+ _chart.order = function(_) {
3089
+ if (!arguments.length) return _order;
3090
+ _order = _;
3091
+ return _chart;
3092
+ };
3093
+
3094
+ return _chart.anchor(parent, chartGroup);
3095
+ };
3096
+
3097
+ dc.bubbleChart = function(parent, chartGroup) {
3098
+ var _chart = dc.abstractBubbleChart(dc.coordinateGridChart({}));
3099
+
3100
+ var _elasticRadius = false;
3101
+
3102
+ _chart.transitionDuration(750);
3103
+
3104
+ var bubbleLocator = function(d) {
3105
+ return "translate(" + (bubbleX(d)) + "," + (bubbleY(d)) + ")";
3106
+ };
3107
+
3108
+ _chart.elasticRadius = function(_) {
3109
+ if (!arguments.length) return _elasticRadius;
3110
+ _elasticRadius = _;
3111
+ return _chart;
3112
+ };
3113
+
3114
+ _chart.plotData = function() {
3115
+ if (_elasticRadius)
3116
+ _chart.r().domain([_chart.rMin(), _chart.rMax()]);
3117
+
3118
+ _chart.r().range([_chart.MIN_RADIUS, _chart.xAxisLength() * _chart.maxBubbleRelativeSize()]);
3119
+
3120
+ var bubbleG = _chart.chartBodyG().selectAll("g." + _chart.BUBBLE_NODE_CLASS)
3121
+ .data(_chart.group().all());
3122
+
3123
+ renderNodes(bubbleG);
3124
+
3125
+ updateNodes(bubbleG);
3126
+
3127
+ removeNodes(bubbleG);
3128
+
3129
+ _chart.fadeDeselectedArea();
3130
+ };
3131
+
3132
+ function renderNodes(bubbleG) {
3133
+ var bubbleGEnter = bubbleG.enter().append("g");
3134
+
3135
+ bubbleGEnter
3136
+ .attr("class", _chart.BUBBLE_NODE_CLASS)
3137
+ .attr("transform", bubbleLocator)
3138
+ .append("circle").attr("class", function(d, i) {
3139
+ return _chart.BUBBLE_CLASS + " _" + i;
3140
+ })
3141
+ .on("click", _chart.onClick)
3142
+ .attr("fill", _chart.initBubbleColor)
3143
+ .attr("r", 0);
3144
+ dc.transition(bubbleG, _chart.transitionDuration())
3145
+ .attr("r", function(d) {
3146
+ return _chart.bubbleR(d);
3147
+ })
3148
+ .attr("opacity", function(d) {
3149
+ return (_chart.bubbleR(d) > 0) ? 1 : 0;
3150
+ });
3151
+
3152
+ _chart.doRenderLabel(bubbleGEnter);
3153
+
3154
+ _chart.doRenderTitles(bubbleGEnter);
3155
+ }
3156
+
3157
+ function updateNodes(bubbleG) {
3158
+ dc.transition(bubbleG, _chart.transitionDuration())
3159
+ .attr("transform", bubbleLocator)
3160
+ .selectAll("circle." + _chart.BUBBLE_CLASS)
3161
+ .attr("fill", _chart.updateBubbleColor)
3162
+ .attr("r", function(d) {
3163
+ return _chart.bubbleR(d);
3164
+ })
3165
+ .attr("opacity", function(d) {
3166
+ return (_chart.bubbleR(d) > 0) ? 1 : 0;
3167
+ });
3168
+
3169
+ _chart.doUpdateLabels(bubbleG);
3170
+ _chart.doUpdateTitles(bubbleG);
3171
+ }
3172
+
3173
+ function removeNodes(bubbleG) {
3174
+ bubbleG.exit().remove();
3175
+ }
3176
+
3177
+ function bubbleX(d) {
3178
+ var x = _chart.x()(_chart.keyAccessor()(d));
3179
+ if (isNaN(x))
3180
+ x = 0;
3181
+ return x;
3182
+ }
3183
+
3184
+ function bubbleY(d) {
3185
+ var y = _chart.y()(_chart.valueAccessor()(d));
3186
+ if (isNaN(y))
3187
+ y = 0;
3188
+ return y;
3189
+ }
3190
+
3191
+ _chart.renderBrush = function(g) {
3192
+ // override default x axis brush from parent chart
3193
+ };
3194
+
3195
+ _chart.redrawBrush = function(g) {
3196
+ // override default x axis brush from parent chart
3197
+ _chart.fadeDeselectedArea();
3198
+ };
3199
+
3200
+ return _chart.anchor(parent, chartGroup);
3201
+ };
3202
+
3203
+ dc.compositeChart = function (parent, chartGroup) {
3204
+ var SUB_CHART_CLASS = "sub";
3205
+
3206
+ var _chart = dc.coordinateGridChart({});
3207
+ var _children = [];
3208
+
3209
+ _chart.transitionDuration(500);
3210
+
3211
+ dc.override(_chart, "generateG", function () {
3212
+ var g = this._generateG();
3213
+
3214
+ for (var i = 0; i < _children.length; ++i) {
3215
+ var child = _children[i];
3216
+
3217
+ generateChildG(child, i);
3218
+
3219
+ if (child.dimension() === undefined) child.dimension(_chart.dimension());
3220
+ if (child.group() === undefined) child.group(_chart.group());
3221
+ child.chartGroup(_chart.chartGroup());
3222
+ child.svg(_chart.svg());
3223
+ child.xUnits(_chart.xUnits());
3224
+ child.transitionDuration(_chart.transitionDuration());
3225
+ child.brushOn(_chart.brushOn());
3226
+ }
3227
+
3228
+ return g;
3229
+ });
3230
+
3231
+ function generateChildG(child, i) {
3232
+ child.generateG(_chart.g());
3233
+ child.g().attr("class", SUB_CHART_CLASS + " _" + i);
3234
+ }
3235
+
3236
+ _chart.plotData = function () {
3237
+ for (var i = 0; i < _children.length; ++i) {
3238
+ var child = _children[i];
3239
+
3240
+ if (child.g() === undefined) {
3241
+ generateChildG(child, i);
3242
+ }
3243
+
3244
+ child.x(_chart.x());
3245
+ child.y(_chart.y());
3246
+ child.xAxis(_chart.xAxis());
3247
+ child.yAxis(_chart.yAxis());
3248
+
3249
+ child.plotData();
3250
+
3251
+ child.activateRenderlets();
3252
+ }
3253
+ };
3254
+
3255
+ _chart.fadeDeselectedArea = function () {
3256
+ for (var i = 0; i < _children.length; ++i) {
3257
+ var child = _children[i];
3258
+ child.brush(_chart.brush());
3259
+ child.fadeDeselectedArea();
3260
+ }
3261
+ };
3262
+
3263
+ _chart.compose = function (charts) {
3264
+ _children = charts;
3265
+ for (var i = 0; i < _children.length; ++i) {
3266
+ var child = _children[i];
3267
+ child.height(_chart.height());
3268
+ child.width(_chart.width());
3269
+ child.margins(_chart.margins());
3270
+ }
3271
+ return _chart;
3272
+ };
3273
+
3274
+ _chart.children = function () {
3275
+ return _children;
3276
+ };
3277
+
3278
+ function getAllYAxisMinFromChildCharts() {
3279
+ var allMins = [];
3280
+ for (var i = 0; i < _children.length; ++i) {
3281
+ allMins.push(_children[i].yAxisMin());
3282
+ }
3283
+ return allMins;
3284
+ }
3285
+
3286
+ _chart.yAxisMin = function () {
3287
+ return d3.min(getAllYAxisMinFromChildCharts());
3288
+ };
3289
+
3290
+ function getAllYAxisMaxFromChildCharts() {
3291
+ var allMaxes = [];
3292
+ for (var i = 0; i < _children.length; ++i) {
3293
+ allMaxes.push(_children[i].yAxisMax());
3294
+ }
3295
+ return allMaxes;
3296
+ }
3297
+
3298
+ _chart.yAxisMax = function () {
3299
+ return dc.utils.add(d3.max(getAllYAxisMaxFromChildCharts()), _chart.yAxisPadding());
3300
+ };
3301
+
3302
+ function getAllXAxisMinFromChildCharts() {
3303
+ var allMins = [];
3304
+ for (var i = 0; i < _children.length; ++i) {
3305
+ allMins.push(_children[i].xAxisMin());
3306
+ }
3307
+ return allMins;
3308
+ }
3309
+
3310
+ _chart.xAxisMin = function () {
3311
+ return dc.utils.subtract(d3.min(getAllXAxisMinFromChildCharts()), _chart.xAxisPadding());
3312
+ };
3313
+
3314
+ function getAllXAxisMaxFromChildCharts() {
3315
+ var allMaxes = [];
3316
+ for (var i = 0; i < _children.length; ++i) {
3317
+ allMaxes.push(_children[i].xAxisMax());
3318
+ }
3319
+ return allMaxes;
3320
+ }
3321
+
3322
+ _chart.xAxisMax = function () {
3323
+ return dc.utils.add(d3.max(getAllXAxisMaxFromChildCharts()), _chart.xAxisPadding());
3324
+ };
3325
+
3326
+ _chart.legendables = function () {
3327
+ var items = [];
3328
+
3329
+ for (var j = 0; j < _children.length; ++j) {
3330
+ var childChart = _children[j];
3331
+ childChart.allGroups().forEach(function (g, i) {
3332
+ items.push(dc.utils.createLegendable(childChart, g, i, childChart.getValueAccessorByIndex(i)));
3333
+ });
3334
+ }
3335
+
3336
+ return items;
3337
+ };
3338
+
3339
+ _chart.legendHighlight = function (d) {
3340
+ for (var j = 0; j < _children.length; ++j) {
3341
+ var child = _children[j];
3342
+ child.legendHighlight(d);
3343
+ }
3344
+ };
3345
+
3346
+ _chart.legendReset = function (d) {
3347
+ for (var j = 0; j < _children.length; ++j) {
3348
+ var child = _children[j];
3349
+ child.legendReset(d);
3350
+ }
3351
+ };
3352
+
3353
+ return _chart.anchor(parent, chartGroup);
3354
+ };
3355
+
3356
+ dc.geoChoroplethChart = function (parent, chartGroup) {
3357
+ var _chart = dc.colorChart(dc.baseChart({}));
3358
+
3359
+ _chart.colorAccessor(function (d, i) {
3360
+ return d;
3361
+ });
3362
+
3363
+ var _geoPath = d3.geo.path();
3364
+ var _projectionFlag;
3365
+
3366
+ var _geoJsons = [];
3367
+
3368
+ _chart.doRender = function () {
3369
+ _chart.resetSvg();
3370
+ for (var layerIndex = 0; layerIndex < _geoJsons.length; ++layerIndex) {
3371
+ var states = _chart.svg().append("g")
3372
+ .attr("class", "layer" + layerIndex);
3373
+
3374
+ var regionG = states.selectAll("g." + geoJson(layerIndex).name)
3375
+ .data(geoJson(layerIndex).data)
3376
+ .enter()
3377
+ .append("g")
3378
+ .attr("class", geoJson(layerIndex).name);
3379
+
3380
+ regionG
3381
+ .append("path")
3382
+ .attr("fill", "white")
3383
+ .attr("d", _geoPath);
3384
+
3385
+ regionG.append("title");
3386
+
3387
+ plotData(layerIndex);
3388
+ }
3389
+ _projectionFlag = false;
3390
+ };
3391
+
3392
+ function plotData(layerIndex) {
3393
+ var maxValue = dc.utils.groupMax(_chart.group(), _chart.valueAccessor());
3394
+ var data = generateLayeredData();
3395
+
3396
+ if (isDataLayer(layerIndex)) {
3397
+ var regionG = renderRegionG(layerIndex);
3398
+
3399
+ renderPaths(regionG, layerIndex, data, maxValue);
3400
+
3401
+ renderTitle(regionG, layerIndex, data);
3402
+ }
3403
+ }
3404
+
3405
+ function generateLayeredData() {
3406
+ var data = {};
3407
+ var groupAll = _chart.group().all();
3408
+ for (var i = 0; i < groupAll.length; ++i) {
3409
+ data[_chart.keyAccessor()(groupAll[i])] = _chart.valueAccessor()(groupAll[i]);
3410
+ }
3411
+ return data;
3412
+ }
3413
+
3414
+ function isDataLayer(layerIndex) {
3415
+ return geoJson(layerIndex).keyAccessor;
3416
+ }
3417
+
3418
+ function renderRegionG(layerIndex) {
3419
+ var regionG = _chart.svg()
3420
+ .selectAll(layerSelector(layerIndex))
3421
+ .classed("selected", function (d) {
3422
+ return isSelected(layerIndex, d);
3423
+ })
3424
+ .classed("deselected", function (d) {
3425
+ return isDeselected(layerIndex, d);
3426
+ })
3427
+ .attr("class", function (d) {
3428
+ var layerNameClass = geoJson(layerIndex).name;
3429
+ var regionClass = dc.utils.nameToId(geoJson(layerIndex).keyAccessor(d));
3430
+ var baseClasses = layerNameClass + " " + regionClass;
3431
+ if (isSelected(layerIndex, d)) baseClasses += " selected";
3432
+ if (isDeselected(layerIndex, d)) baseClasses += " deselected";
3433
+ return baseClasses;
3434
+ });
3435
+ return regionG;
3436
+ }
3437
+
3438
+ function layerSelector(layerIndex) {
3439
+ return "g.layer" + layerIndex + " g." + geoJson(layerIndex).name;
3440
+ }
3441
+
3442
+ function isSelected(layerIndex, d) {
3443
+ return _chart.hasFilter() && _chart.hasFilter(getKey(layerIndex, d));
3444
+ }
3445
+
3446
+ function isDeselected(layerIndex, d) {
3447
+ return _chart.hasFilter() && !_chart.hasFilter(getKey(layerIndex, d));
3448
+ }
3449
+
3450
+ function getKey(layerIndex, d) {
3451
+ return geoJson(layerIndex).keyAccessor(d);
3452
+ }
3453
+
3454
+ function geoJson(index) {
3455
+ return _geoJsons[index];
3456
+ }
3457
+
3458
+ function renderPaths(regionG, layerIndex, data) {
3459
+ var paths = regionG
3460
+ .select("path")
3461
+ .attr("fill", function (d) {
3462
+ var currentFill = d3.select(this).attr("fill");
3463
+ if (currentFill)
3464
+ return currentFill;
3465
+ return "none";
3466
+ })
3467
+ .on("click", function (d) {
3468
+ return _chart.onClick(d, layerIndex);
3469
+ });
3470
+
3471
+ dc.transition(paths, _chart.transitionDuration()).attr("fill", function (d, i) {
3472
+ return _chart.getColor(data[geoJson(layerIndex).keyAccessor(d)], i);
3473
+ });
3474
+ }
3475
+
3476
+ _chart.onClick = function (d, layerIndex) {
3477
+ var selectedRegion = geoJson(layerIndex).keyAccessor(d);
3478
+ dc.events.trigger(function () {
3479
+ _chart.filter(selectedRegion);
3480
+ dc.redrawAll(_chart.chartGroup());
3481
+ });
3482
+ };
3483
+
3484
+ function renderTitle(regionG, layerIndex, data) {
3485
+ if (_chart.renderTitle()) {
3486
+ regionG.selectAll("title").text(function (d) {
3487
+ var key = getKey(layerIndex, d);
3488
+ var value = data[key];
3489
+ return _chart.title()({key: key, value: value});
3490
+ });
3491
+ }
3492
+ }
3493
+
3494
+ _chart.doRedraw = function () {
3495
+ for (var layerIndex = 0; layerIndex < _geoJsons.length; ++layerIndex) {
3496
+ plotData(layerIndex);
3497
+ if(_projectionFlag) {
3498
+ _chart.svg().selectAll("g." + geoJson(layerIndex).name + " path").attr("d", _geoPath);
3499
+ }
3500
+ }
3501
+ _projectionFlag = false;
3502
+ };
3503
+
3504
+ _chart.overlayGeoJson = function (json, name, keyAccessor) {
3505
+ for (var i = 0; i < _geoJsons.length; ++i) {
3506
+ if (_geoJsons[i].name == name) {
3507
+ _geoJsons[i].data = json;
3508
+ _geoJsons[i].keyAccessor = keyAccessor;
3509
+ return _chart;
3510
+ }
3511
+ }
3512
+ _geoJsons.push({name: name, data: json, keyAccessor: keyAccessor});
3513
+ return _chart;
3514
+ };
3515
+
3516
+ _chart.projection = function (projection) {
3517
+ _geoPath.projection(projection);
3518
+ _projectionFlag = true;
3519
+ return _chart;
3520
+ };
3521
+
3522
+ _chart.geoJsons = function () {
3523
+ return _geoJsons;
3524
+ };
3525
+
3526
+ _chart.removeGeoJson = function (name) {
3527
+ var geoJsons = [];
3528
+
3529
+ for (var i = 0; i < _geoJsons.length; ++i) {
3530
+ var layer = _geoJsons[i];
3531
+ if (layer.name != name) {
3532
+ geoJsons.push(layer);
3533
+ }
3534
+ }
3535
+
3536
+ _geoJsons = geoJsons;
3537
+
3538
+ return _chart;
3539
+ };
3540
+
3541
+ return _chart.anchor(parent, chartGroup);
3542
+ };
3543
+
3544
+ dc.bubbleOverlay = function(root, chartGroup) {
3545
+ var BUBBLE_OVERLAY_CLASS = "bubble-overlay";
3546
+ var BUBBLE_NODE_CLASS = "node";
3547
+ var BUBBLE_CLASS = "bubble";
3548
+
3549
+ var _chart = dc.abstractBubbleChart(dc.baseChart({}));
3550
+ var _g;
3551
+ var _points = [];
3552
+
3553
+ _chart.transitionDuration(750);
3554
+
3555
+ _chart.radiusValueAccessor(function(d) {
3556
+ return d.value;
3557
+ });
3558
+
3559
+ _chart.point = function(name, x, y) {
3560
+ _points.push({name: name, x: x, y: y});
3561
+ return _chart;
3562
+ };
3563
+
3564
+ _chart.doRender = function() {
3565
+ _g = initOverlayG();
3566
+
3567
+ _chart.r().range([_chart.MIN_RADIUS, _chart.width() * _chart.maxBubbleRelativeSize()]);
3568
+
3569
+ initializeBubbles();
3570
+
3571
+ _chart.fadeDeselectedArea();
3572
+
3573
+ return _chart;
3574
+ };
3575
+
3576
+ function initOverlayG() {
3577
+ _g = _chart.select("g." + BUBBLE_OVERLAY_CLASS);
3578
+ if (_g.empty())
3579
+ _g = _chart.svg().append("g").attr("class", BUBBLE_OVERLAY_CLASS);
3580
+ return _g;
3581
+ }
3582
+
3583
+ function initializeBubbles() {
3584
+ var data = mapData();
3585
+
3586
+ _points.forEach(function(point) {
3587
+ var nodeG = getNodeG(point, data);
3588
+
3589
+ var circle = nodeG.select("circle." + BUBBLE_CLASS);
3590
+
3591
+ if (circle.empty())
3592
+ circle = nodeG.append("circle")
3593
+ .attr("class", BUBBLE_CLASS)
3594
+ .attr("r", 0)
3595
+ .attr("fill", _chart.initBubbleColor)
3596
+ .on("click", _chart.onClick);
3597
+
3598
+ dc.transition(circle, _chart.transitionDuration())
3599
+ .attr("r", function(d) {
3600
+ return _chart.bubbleR(d);
3601
+ });
3602
+
3603
+ _chart.doRenderLabel(nodeG);
3604
+
3605
+ _chart.doRenderTitles(nodeG);
3606
+ });
3607
+ }
3608
+
3609
+ function mapData() {
3610
+ var data = {};
3611
+ _chart.group().all().forEach(function(datum) {
3612
+ data[_chart.keyAccessor()(datum)] = datum;
3613
+ });
3614
+ return data;
3615
+ }
3616
+
3617
+ function getNodeG(point, data) {
3618
+ var bubbleNodeClass = BUBBLE_NODE_CLASS + " " + dc.utils.nameToId(point.name);
3619
+
3620
+ var nodeG = _g.select("g." + dc.utils.nameToId(point.name));
3621
+
3622
+ if (nodeG.empty()) {
3623
+ nodeG = _g.append("g")
3624
+ .attr("class", bubbleNodeClass)
3625
+ .attr("transform", "translate(" + point.x + "," + point.y + ")");
3626
+ }
3627
+
3628
+ nodeG.datum(data[point.name]);
3629
+
3630
+ return nodeG;
3631
+ }
3632
+
3633
+ _chart.doRedraw = function() {
3634
+ updateBubbles();
3635
+
3636
+ _chart.fadeDeselectedArea();
3637
+
3638
+ return _chart;
3639
+ };
3640
+
3641
+ function updateBubbles() {
3642
+ var data = mapData();
3643
+
3644
+ _points.forEach(function(point) {
3645
+ var nodeG = getNodeG(point, data);
3646
+
3647
+ var circle = nodeG.select("circle." + BUBBLE_CLASS);
3648
+
3649
+ dc.transition(circle, _chart.transitionDuration())
3650
+ .attr("r", function(d) {
3651
+ return _chart.bubbleR(d);
3652
+ })
3653
+ .attr("fill", _chart.updateBubbleColor);
3654
+
3655
+ _chart.doUpdateLabels(nodeG);
3656
+
3657
+ _chart.doUpdateTitles(nodeG);
3658
+ });
3659
+ }
3660
+
3661
+ _chart.debug = function(flag) {
3662
+ if(flag){
3663
+ var debugG = _chart.select("g." + dc.constants.DEBUG_GROUP_CLASS);
3664
+
3665
+ if(debugG.empty())
3666
+ debugG = _chart.svg()
3667
+ .append("g")
3668
+ .attr("class", dc.constants.DEBUG_GROUP_CLASS);
3669
+
3670
+ var debugText = debugG.append("text")
3671
+ .attr("x", 10)
3672
+ .attr("y", 20);
3673
+
3674
+ debugG
3675
+ .append("rect")
3676
+ .attr("width", _chart.width())
3677
+ .attr("height", _chart.height())
3678
+ .on("mousemove", function() {
3679
+ var position = d3.mouse(debugG.node());
3680
+ var msg = position[0] + ", " + position[1];
3681
+ debugText.text(msg);
3682
+ });
3683
+ }else{
3684
+ _chart.selectAll(".debug").remove();
3685
+ }
3686
+
3687
+ return _chart;
3688
+ };
3689
+
3690
+ _chart.anchor(root, chartGroup);
3691
+
3692
+ return _chart;
3693
+ };
3694
+
3695
+ dc.rowChart = function (parent, chartGroup) {
3696
+
3697
+ var _g;
3698
+
3699
+ var _labelOffsetX = 10;
3700
+
3701
+ var _labelOffsetY = 15;
3702
+
3703
+ var _gap = 5;
3704
+
3705
+ var _rowCssClass = "row";
3706
+
3707
+ var _chart = dc.marginable(dc.colorChart(dc.baseChart({})));
3708
+
3709
+ var _x;
3710
+
3711
+ var _elasticX;
3712
+
3713
+ var _xAxis = d3.svg.axis().orient("bottom");
3714
+
3715
+ function calculateAxisScale() {
3716
+ if (!_x || _elasticX) {
3717
+ var extent = d3.extent(_chart.group().all(), _chart.valueAccessor());
3718
+ if (extent[0] > 0) extent[0] = 0;
3719
+ _x = d3.scale.linear().domain(extent)
3720
+ .range([0, _chart.effectiveWidth()]);
3721
+
3722
+ _xAxis.scale(_x);
3723
+ }
3724
+ }
3725
+
3726
+ function drawAxis() {
3727
+ var axisG = _g.select("g.axis");
3728
+
3729
+ calculateAxisScale();
3730
+
3731
+ if (axisG.empty())
3732
+ axisG = _g.append("g").attr("class", "axis")
3733
+ .attr("transform", "translate(0, " + _chart.effectiveHeight() + ")");
3734
+
3735
+ dc.transition(axisG, _chart.transitionDuration())
3736
+ .call(_xAxis);
3737
+ }
3738
+
3739
+ _chart.doRender = function () {
3740
+ _chart.resetSvg();
3741
+
3742
+ _g = _chart.svg()
3743
+ .append("g")
3744
+ .attr("transform", "translate(" + _chart.margins().left + "," + _chart.margins().top + ")");
3745
+
3746
+ drawAxis();
3747
+ drawGridLines();
3748
+ drawChart();
3749
+
3750
+ return _chart;
3751
+ };
3752
+
3753
+ _chart.title(function (d) {
3754
+ return _chart.keyAccessor()(d) + ": " + _chart.valueAccessor()(d);
3755
+ });
3756
+
3757
+ _chart.label(function (d) {
3758
+ return _chart.keyAccessor()(d);
3759
+ });
3760
+
3761
+ _chart.x = function(x){
3762
+ if(!arguments.length) return _x;
3763
+ _x = x;
3764
+ return _chart;
3765
+ };
3766
+
3767
+ function drawGridLines() {
3768
+ _g.selectAll("g.tick")
3769
+ .select("line.grid-line")
3770
+ .remove();
3771
+
3772
+ _g.selectAll("g.tick")
3773
+ .append("line")
3774
+ .attr("class", "grid-line")
3775
+ .attr("x1", 0)
3776
+ .attr("y1", 0)
3777
+ .attr("x2", 0)
3778
+ .attr("y2", function (d) {
3779
+ return -_chart.effectiveHeight();
3780
+ });
3781
+ }
3782
+
3783
+ function drawChart() {
3784
+ drawAxis();
3785
+ drawGridLines();
3786
+
3787
+ var rows = _g.selectAll("g." + _rowCssClass)
3788
+ .data(_chart.group().all());
3789
+
3790
+ createElements(rows);
3791
+ removeElements(rows);
3792
+ updateElements(rows);
3793
+ }
3794
+
3795
+ function createElements(rows) {
3796
+ var rowEnter = rows.enter()
3797
+ .append("g")
3798
+ .attr("class", function (d, i) {
3799
+ return _rowCssClass + " _" + i;
3800
+ });
3801
+
3802
+ rowEnter.append("rect").attr("width", 0);
3803
+
3804
+ createLabels(rowEnter);
3805
+ updateLabels(rows);
3806
+ }
3807
+
3808
+ function removeElements(rows) {
3809
+ rows.exit().remove();
3810
+ }
3811
+
3812
+ function updateElements(rows) {
3813
+ var height = rowHeight();
3814
+
3815
+ var rect = rows.attr("transform",function (d, i) {
3816
+ return "translate(0," + ((i + 1) * _gap + i * height) + ")";
3817
+ }).select("rect")
3818
+ .attr("height", height)
3819
+ .attr("fill", _chart.getColor)
3820
+ .on("click", onClick)
3821
+ .classed("deselected", function (d) {
3822
+ return (_chart.hasFilter()) ? !_chart.isSelectedRow(d) : false;
3823
+ })
3824
+ .classed("selected", function (d) {
3825
+ return (_chart.hasFilter()) ? _chart.isSelectedRow(d) : false;
3826
+ });
3827
+
3828
+ dc.transition(rect, _chart.transitionDuration())
3829
+ .attr("width", function (d) {
3830
+ return Math.abs(_x(0) - _x(_chart.valueAccessor()(d)));
3831
+ })
3832
+ .attr("transform", translateX);
3833
+
3834
+ createTitles(rows);
3835
+ updateLabels(rows);
3836
+ }
3837
+
3838
+ function createTitles(rows) {
3839
+ if (_chart.renderTitle()) {
3840
+ rows.selectAll("title").remove();
3841
+ rows.append("title").text(function (d) {
3842
+ return _chart.title()(d);
3843
+ });
3844
+ }
3845
+ }
3846
+
3847
+ function createLabels(rowEnter) {
3848
+ if (_chart.renderLabel()) {
3849
+ rowEnter.append("text")
3850
+ .on("click", onClick);
3851
+ }
3852
+ }
3853
+
3854
+ function updateLabels(rows) {
3855
+ if (_chart.renderLabel()) {
3856
+ var lab = rows.select("text")
3857
+ .attr("x", _labelOffsetX)
3858
+ .attr("y", _labelOffsetY)
3859
+ .attr("class", function (d, i) {
3860
+ return _rowCssClass + " _" + i;
3861
+ })
3862
+ .text(function (d) {
3863
+ return _chart.label()(d);
3864
+ });
3865
+ dc.transition(lab, _chart.transitionDuration())
3866
+ .attr("transform", translateX);
3867
+ }
3868
+ }
3869
+
3870
+ function numberOfRows() {
3871
+ return _chart.group().all().length;
3872
+ }
3873
+
3874
+ function rowHeight() {
3875
+ var n = numberOfRows();
3876
+ return (_chart.effectiveHeight() - (n + 1) * _gap) / n;
3877
+ }
3878
+
3879
+ function onClick(d) {
3880
+ _chart.onClick(d);
3881
+ }
3882
+
3883
+ function translateX(d) {
3884
+ var x = _x(_chart.valueAccessor()(d)),
3885
+ x0 = _x(0),
3886
+ s = x > x0 ? x0 : x;
3887
+ return "translate("+s+",0)";
3888
+ }
3889
+
3890
+ _chart.doRedraw = function () {
3891
+ drawChart();
3892
+ return _chart;
3893
+ };
3894
+
3895
+ _chart.xAxis = function () {
3896
+ return _xAxis;
3897
+ };
3898
+
3899
+ _chart.gap = function (g) {
3900
+ if (!arguments.length) return _gap;
3901
+ _gap = g;
3902
+ return _chart;
3903
+ };
3904
+
3905
+ _chart.elasticX = function (_) {
3906
+ if (!arguments.length) return _elasticX;
3907
+ _elasticX = _;
3908
+ return _chart;
3909
+ };
3910
+
3911
+ _chart.labelOffsetX = function (o) {
3912
+ if (!arguments.length) return _labelOffsetX;
3913
+ _labelOffsetX = o;
3914
+ return _chart;
3915
+ };
3916
+
3917
+ _chart.labelOffsetY = function (o) {
3918
+ if (!arguments.length) return _labelOffsetY;
3919
+ _labelOffsetY = o;
3920
+ return _chart;
3921
+ };
3922
+
3923
+ _chart.isSelectedRow = function (d) {
3924
+ return _chart.hasFilter(_chart.keyAccessor()(d));
3925
+ };
3926
+
3927
+ return _chart.anchor(parent, chartGroup);
3928
+ };
3929
+
3930
+ dc.legend = function () {
3931
+ var LABEL_GAP = 2;
3932
+
3933
+ var _legend = {},
3934
+ _parent,
3935
+ _x = 0,
3936
+ _y = 0,
3937
+ _itemHeight = 12,
3938
+ _gap = 5;
3939
+
3940
+ var _g;
3941
+
3942
+ _legend.parent = function (p) {
3943
+ if (!arguments.length) return _parent;
3944
+ _parent = p;
3945
+ return _legend;
3946
+ };
3947
+
3948
+ _legend.render = function () {
3949
+ _g = _parent.svg().append("g")
3950
+ .attr("class", "dc-legend")
3951
+ .attr("transform", "translate(" + _x + "," + _y + ")");
3952
+
3953
+ var itemEnter = _g.selectAll('g.dc-legend-item')
3954
+ .data(_parent.legendables())
3955
+ .enter()
3956
+ .append("g")
3957
+ .attr("class", "dc-legend-item")
3958
+ .attr("transform", function (d, i) {
3959
+ return "translate(0," + i * legendItemHeight() + ")";
3960
+ })
3961
+ .on("mouseover", function(d){
3962
+ _parent.legendHighlight(d);
3963
+ })
3964
+ .on("mouseout", function (d) {
3965
+ _parent.legendReset(d);
3966
+ });
3967
+
3968
+ itemEnter
3969
+ .append("rect")
3970
+ .attr("width", _itemHeight)
3971
+ .attr("height", _itemHeight)
3972
+ .attr("fill", function(d){return d.color;});
3973
+
3974
+ itemEnter.append("text")
3975
+ .text(function(d){return d.name;})
3976
+ .attr("x", _itemHeight + LABEL_GAP)
3977
+ .attr("y", function(){return _itemHeight / 2 + (this.clientHeight?this.clientHeight:13) / 2 - 2;});
3978
+ };
3979
+
3980
+ function legendItemHeight() {
3981
+ return _gap + _itemHeight;
3982
+ }
3983
+
3984
+ _legend.x = function (x) {
3985
+ if (!arguments.length) return _x;
3986
+ _x = x;
3987
+ return _legend;
3988
+ };
3989
+
3990
+ _legend.y = function (y) {
3991
+ if (!arguments.length) return _y;
3992
+ _y = y;
3993
+ return _legend;
3994
+ };
3995
+
3996
+ _legend.gap = function (gap) {
3997
+ if (!arguments.length) return _gap;
3998
+ _gap = gap;
3999
+ return _legend;
4000
+ };
4001
+
4002
+ _legend.itemHeight = function (h) {
4003
+ if (!arguments.length) return _itemHeight;
4004
+ _itemHeight = h;
4005
+ return _legend;
4006
+ };
4007
+
4008
+ return _legend;
4009
+ };
4010
+
4011
+ dc.scatterPlot = function (parent, chartGroup) {
4012
+ var _chart = dc.coordinateGridChart({});
4013
+
4014
+ _chart.plotData = function(){
4015
+ _chart.chartBodyG().selectAll("path.dc-symbol")
4016
+ .data(_chart.group().all())
4017
+ .enter()
4018
+ .append("path")
4019
+ .attr("class", "dc-symbol")
4020
+ .attr("transform", function(d){
4021
+ return "translate("+_chart.x()(_chart.keyAccessor()(d))+","+_chart.y()(_chart.valueAccessor()(d))+")";
4022
+ })
4023
+ .attr("d", d3.svg.symbol());
4024
+ };
4025
+
4026
+ return _chart.anchor(parent, chartGroup);
4027
+ };
4028
+
4029
+ dc.numberDisplay = function (parent, chartGroup) {
4030
+ var SPAN_CLASS = 'number-display';
4031
+ var _formatNumber = d3.format(".2s");
4032
+ var _chart = dc.baseChart({});
4033
+
4034
+ _chart.dimension({}); // dummy dimension to remove warnings
4035
+
4036
+ _chart.value = function () {
4037
+ var valObj = _chart.group().all && _chart.group().all()[0] || _chart.group().value();
4038
+ return _chart.valueAccessor()(valObj);
4039
+ };
4040
+
4041
+ _chart.doRender = function () {
4042
+ var newValue = _chart.value(),
4043
+ span = _chart.selectAll("."+SPAN_CLASS);
4044
+
4045
+ if(span.empty())
4046
+ span = span.data([0])
4047
+ .enter()
4048
+ .append("span")
4049
+ .attr("class", SPAN_CLASS);
4050
+
4051
+ span.transition()
4052
+ .duration(250)
4053
+ .ease('quad-out-in')
4054
+ .tween("text", function () {
4055
+ var interp = d3.interpolateNumber(this.lastValue || 0, newValue);
4056
+ this.lastValue = newValue;
4057
+ return function (t) {
4058
+ this.textContent = _chart.formatNumber()(interp(t));
4059
+ };
4060
+ });
4061
+
4062
+ return _chart;
4063
+ };
4064
+
4065
+ _chart.doRedraw = function(){
4066
+ return _chart.doRender();
4067
+ };
4068
+
4069
+ _chart.formatNumber = function (_) {
4070
+ if (!arguments.length) return _formatNumber;
4071
+ _formatNumber = _;
4072
+ return _chart;
4073
+ };
4074
+
4075
+ return _chart.anchor(parent, chartGroup);
4076
+ };
4077
+
4078
+ return dc;})();