pyk 0.2.6 → 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +8 -8
  2. data/app/assets/javascripts/lib/chardinjs.min.js +2 -0
  3. data/app/assets/javascripts/lib/crossfilter.js +1383 -1
  4. data/app/assets/javascripts/lib/{d3.js → d3.v3.js} +0 -0
  5. data/app/assets/javascripts/lib/dc.js +3492 -757
  6. data/app/assets/javascripts/lib/jquery.gridster.js +2 -3621
  7. data/app/assets/javascripts/lib/markermanager.js +2 -980
  8. data/app/assets/javascripts/lib/underscore.js +1276 -0
  9. data/app/assets/javascripts/nvd3/lib/colorbrewer.js +302 -0
  10. data/app/assets/javascripts/nvd3/lib/crossfilter.js +1180 -0
  11. data/app/assets/javascripts/nvd3/lib/crossfilter.min.js +1 -0
  12. data/app/assets/javascripts/nvd3/lib/d3.v2.js +7033 -0
  13. data/app/assets/javascripts/nvd3/lib/d3.v2.min.js +4 -0
  14. data/app/assets/javascripts/nvd3/lib/d3.v3.js +8436 -0
  15. data/app/assets/javascripts/nvd3/lib/fisheye.js +86 -0
  16. data/app/assets/javascripts/nvd3/lib/hive.js +80 -0
  17. data/app/assets/javascripts/nvd3/lib/horizon.js +192 -0
  18. data/app/assets/javascripts/nvd3/lib/sankey.js +292 -0
  19. data/app/assets/javascripts/nvd3/nv.d3.js +14312 -0
  20. data/app/assets/javascripts/nvd3/nv.d3.min.js +6 -0
  21. data/app/assets/javascripts/nvd3/src/core.js +122 -0
  22. data/app/assets/javascripts/nvd3/src/interactiveLayer.js +251 -0
  23. data/app/assets/javascripts/nvd3/src/models/axis.js +405 -0
  24. data/app/assets/javascripts/nvd3/src/models/backup/bullet.js +250 -0
  25. data/app/assets/javascripts/nvd3/src/models/backup/bulletChart.js +349 -0
  26. data/app/assets/javascripts/nvd3/src/models/boilerplate.js +104 -0
  27. data/app/assets/javascripts/nvd3/src/models/bullet.js +385 -0
  28. data/app/assets/javascripts/nvd3/src/models/bulletChart.js +343 -0
  29. data/app/assets/javascripts/nvd3/src/models/cumulativeLineChart.js +782 -0
  30. data/app/assets/javascripts/nvd3/src/models/discreteBar.js +349 -0
  31. data/app/assets/javascripts/nvd3/src/models/discreteBarChart.js +333 -0
  32. data/app/assets/javascripts/nvd3/src/models/distribution.js +148 -0
  33. data/app/assets/javascripts/nvd3/src/models/historicalBar.js +331 -0
  34. data/app/assets/javascripts/nvd3/src/models/historicalBarChart.js +419 -0
  35. data/app/assets/javascripts/nvd3/src/models/indentedTree.js +337 -0
  36. data/app/assets/javascripts/nvd3/src/models/legend.js +270 -0
  37. data/app/assets/javascripts/nvd3/src/models/line.js +284 -0
  38. data/app/assets/javascripts/nvd3/src/models/lineChart.js +465 -0
  39. data/app/assets/javascripts/nvd3/src/models/linePlusBarChart.js +433 -0
  40. data/app/assets/javascripts/nvd3/src/models/linePlusBarWithFocusChart.js +658 -0
  41. data/app/assets/javascripts/nvd3/src/models/lineWithFisheye.js +200 -0
  42. data/app/assets/javascripts/nvd3/src/models/lineWithFisheyeChart.js +297 -0
  43. data/app/assets/javascripts/nvd3/src/models/lineWithFocusChart.js +574 -0
  44. data/app/assets/javascripts/nvd3/src/models/multiBar.js +461 -0
  45. data/app/assets/javascripts/nvd3/src/models/multiBarChart.js +524 -0
  46. data/app/assets/javascripts/nvd3/src/models/multiBarHorizontal.js +424 -0
  47. data/app/assets/javascripts/nvd3/src/models/multiBarHorizontalChart.js +434 -0
  48. data/app/assets/javascripts/nvd3/src/models/multiBarTimeSeries.js +384 -0
  49. data/app/assets/javascripts/nvd3/src/models/multiBarTimeSeriesChart.js +405 -0
  50. data/app/assets/javascripts/nvd3/src/models/multiChart.js +452 -0
  51. data/app/assets/javascripts/nvd3/src/models/ohlcBar.js +380 -0
  52. data/app/assets/javascripts/nvd3/src/models/parallelCoordinates.js +239 -0
  53. data/app/assets/javascripts/nvd3/src/models/pie.js +398 -0
  54. data/app/assets/javascripts/nvd3/src/models/pieChart.js +292 -0
  55. data/app/assets/javascripts/nvd3/src/models/scatter.js +674 -0
  56. data/app/assets/javascripts/nvd3/src/models/scatterChart.js +628 -0
  57. data/app/assets/javascripts/nvd3/src/models/scatterPlusLineChart.js +620 -0
  58. data/app/assets/javascripts/nvd3/src/models/sparkline.js +194 -0
  59. data/app/assets/javascripts/nvd3/src/models/sparklinePlus.js +295 -0
  60. data/app/assets/javascripts/nvd3/src/models/stackedArea.js +368 -0
  61. data/app/assets/javascripts/nvd3/src/models/stackedAreaChart.js +629 -0
  62. data/app/assets/javascripts/nvd3/src/tooltip.js +490 -0
  63. data/app/assets/javascripts/nvd3/src/utils.js +152 -0
  64. data/app/assets/javascripts/pyk.js +1 -0
  65. data/app/assets/stylesheets/lib/chardinjs.css +82 -0
  66. data/app/assets/stylesheets/nvd3/nv.d3.css +769 -0
  67. data/app/assets/stylesheets/pyk.css.scss +1 -0
  68. metadata +61 -2
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZmQzMDcxNDBmNGFkOTJjODkwZmU5NWFkZWVkMjg3OThkZjY0MmU5Zg==
4
+ ZjVjOTVkMzA3NDQ0NjM0Nzk0ZjIwODg1YTA2ZDRjMTU5OGFmMDllNA==
5
5
  data.tar.gz: !binary |-
6
- NWNlNDNlOTY2NGQxYjE0NTUxYzBiMDZkODI1ODFlNjljZWU0NTRmMg==
6
+ NmE1MWM1MDA0MjI4MGYyNjY5ZWYwMjE2ZGNlN2RhMGIwYjcyMzEyMA==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- NDE0Mjg5MzExYjRmNmEzNTAxYmM1NTAwNGZiNDE5MWU3OWVlNjFhNjlmMzA0
10
- Y2EyYmFkNjE0MTIwM2Q5ZjU1YmY5ZWYwMjMwOTcyNDFiMDFiMjBkNGNlMTRj
11
- YmYzMjJjODUxNDRlZjAzMmYzMjhiM2EwYzI4NDQwYmZmODA2YzA=
9
+ OTEwMzc5MWU3MDgyMTIwNjVhMjljODk4MjcxNWJkNzg0YWRhMWQ1NmQwN2Qx
10
+ NjRiNTJjOTAwODQzMTZjZDc2NDhmOTEzODcxOWEzMjAyYTA3YTg0NjhjYzli
11
+ YThiYzE4NTE1NGUxNTA0OTYwZjM2ZTZkMmUxOGY1MzgwMDFjZTA=
12
12
  data.tar.gz: !binary |-
13
- YmU0YjQwYTRjNzA3MDM0NTZiYzc4YmJkZTM4YmFiNjU2ZTM5MDIwMzZhYjBj
14
- NDY2YjJmMDMzYmE3YjQ2ZWEyZGQ2ZTU1YTgxZjMyNWNlYmUxZGU5MjhkNWQw
15
- MzFlMThmMmNlZjk1MWIxNjU4OWJkNGRhNzVhOGJkZmZhZTE0OWI=
13
+ NTk4YTcwYjRlYmI2MzdmM2FhNWY1NmJlZjVkMThhMDZmNDdiMWE4N2JjNzRk
14
+ YmI4YTJiNTc3YWVjODg3YWQxMTZhNTIxY2IxNzA4NGJlYmRiOGM4MDM3OTlh
15
+ NWY0NDBlMGE3NWUwZmQ1Y2QzZTc5OTZkNzYxY2Q5OTE5NWJjMjI=
@@ -0,0 +1,2 @@
1
+ // Generated by CoffeeScript 1.6.2
2
+ (function(){var e=[].slice;(function(t,n){var r;return r=function(){function e(e){var r=this;this.$el=t(e),t(n).resize(function(){return r.refresh()})}return e.prototype.start=function(){var e,t,n,r;if(this._overlay_visible())return!1;this._add_overlay_layer(),r=this.$el.find("*[data-intro]");for(t=0,n=r.length;t<n;t++)e=r[t],this._show_element(e);return this.$el.trigger("chardinJs:start")},e.prototype.toggle=function(){return this._overlay_visible()?this.stop():this.start()},e.prototype.refresh=function(){var e,t,n,r,i;if(this._overlay_visible()){r=this.$el.find("*[data-intro]"),i=[];for(t=0,n=r.length;t<n;t++)e=r[t],i.push(this._position_helper_layer(e));return i}return this},e.prototype.stop=function(){return this.$el.find(".chardinjs-overlay").fadeOut(function(){return t(this).remove()}),this.$el.find(".chardinjs-helper-layer").remove(),this.$el.find(".chardinjs-show-element").removeClass("chardinjs-show-element"),this.$el.find(".chardinjs-relative-position").removeClass("chardinjs-relative-position"),n.removeEventListener?n.removeEventListener("keydown",this._onKeyDown,!0):document.detachEvent&&document.detachEvent("onkeydown",this._onKeyDown),this.$el.trigger("chardinJs:stop")},e.prototype._overlay_visible=function(){return this.$el.find(".chardinjs-overlay").length!==0},e.prototype._add_overlay_layer=function(){var e,t,n,r=this;return this._overlay_visible()?!1:(t=document.createElement("div"),n="",t.className="chardinjs-overlay",this.$el.prop("tagName")==="BODY"?(n+="top: 0;bottom: 0; left: 0;right: 0;position: fixed;",t.setAttribute("style",n)):(e=this._get_offset(this.$el.get()[0]),e&&(n+="width: "+e.width+"px; height:"+e.height+"px; top:"+e.top+"px;left: "+e.left+"px;",t.setAttribute("style",n))),this.$el.get()[0].appendChild(t),t.onclick=function(){return r.stop()},setTimeout(function(){return n+="opacity: .8;",t.setAttribute("style",n)},10))},e.prototype._get_position=function(e){return e.getAttribute("data-position")||"bottom"},e.prototype._place_tooltip=function(e){var n,r,i,s,o,u,a;u=t(e).data("tooltip_layer"),a=this._get_offset(u),u.style.top=null,u.style.right=null,u.style.bottom=null,u.style.left=null;switch(this._get_position(e)){case"top":case"bottom":i=this._get_offset(e),o=i.width,r=t(u).width(),u.style.left=""+(o/2-a.width/2)+"px";break;case"left":case"right":i=this._get_offset(e),s=i.height,n=t(u).height(),u.style.top=""+(s/2-a.height/2)+"px"}switch(this._get_position(e)){case"left":return u.style.left="-"+(a.width-34)+"px";case"right":return u.style.right="-"+(a.width-34)+"px";case"bottom":return u.style.bottom="-"+a.height+"px";case"top":return u.style.top="-"+a.height+"px"}},e.prototype._position_helper_layer=function(e){var n,r;return r=t(e).data("helper_layer"),n=this._get_offset(e),r.setAttribute("style","width: "+n.width+"px; height:"+n.height+"px; top:"+n.top+"px; left: "+n.left+"px;")},e.prototype._show_element=function(e){var n,r,i,s;r=this._get_offset(e),i=document.createElement("div"),s=document.createElement("div"),t(e).data("helper_layer",i).data("tooltip_layer",s),e.id&&i.setAttribute("data-id",e.id),i.className="chardinjs-helper-layer chardinjs-"+this._get_position(e),this._position_helper_layer(e),this.$el.get()[0].appendChild(i),s.className="chardinjs-tooltip chardinjs-"+this._get_position(e),s.innerHTML="<div class='chardinjs-tooltiptext'>"+e.getAttribute("data-intro")+"</div>",i.appendChild(s),this._place_tooltip(e),e.className+=" chardinjs-show-element",n="",e.currentStyle?n=e.currentStyle.position:document.defaultView&&document.defaultView.getComputedStyle&&(n=document.defaultView.getComputedStyle(e,null).getPropertyValue("position")),n=n.toLowerCase();if(n!=="absolute"&&n!=="relative")return e.className+=" chardinjs-relative-position"},e.prototype._get_offset=function(e){var t,n,r;t={width:e.offsetWidth,height:e.offsetHeight},n=0,r=0;while(e&&!isNaN(e.offsetLeft)&&!isNaN(e.offsetTop))n+=e.offsetLeft,r+=e.offsetTop,e=e.offsetParent;return t.top=r,t.left=n,t},e}(),t.fn.extend({chardinJs:function(){var n,i,s,o;return o=arguments[0],i=2<=arguments.length?e.call(arguments,1):[],n=t(this[0]),s=n.data("chardinJs"),s||n.data("chardinJs",s=new r(this,o)),typeof o=="string"&&s[o].apply(s,i),s}})})(window.jQuery,window)}).call(this);
@@ -1 +1,1383 @@
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);
1
+ (function(exports){
2
+ crossfilter.version = "1.3.5";
3
+ function crossfilter_identity(d) {
4
+ return d;
5
+ }
6
+ crossfilter.permute = permute;
7
+
8
+ function permute(array, index) {
9
+ for (var i = 0, n = index.length, copy = new Array(n); i < n; ++i) {
10
+ copy[i] = array[index[i]];
11
+ }
12
+ return copy;
13
+ }
14
+ var bisect = crossfilter.bisect = bisect_by(crossfilter_identity);
15
+
16
+ bisect.by = bisect_by;
17
+
18
+ function bisect_by(f) {
19
+
20
+ // Locate the insertion point for x in a to maintain sorted order. The
21
+ // arguments lo and hi may be used to specify a subset of the array which
22
+ // should be considered; by default the entire array is used. If x is already
23
+ // present in a, the insertion point will be before (to the left of) any
24
+ // existing entries. The return value is suitable for use as the first
25
+ // argument to `array.splice` assuming that a is already sorted.
26
+ //
27
+ // The returned insertion point i partitions the array a into two halves so
28
+ // that all v < x for v in a[lo:i] for the left side and all v >= x for v in
29
+ // a[i:hi] for the right side.
30
+ function bisectLeft(a, x, lo, hi) {
31
+ while (lo < hi) {
32
+ var mid = lo + hi >>> 1;
33
+ if (f(a[mid]) < x) lo = mid + 1;
34
+ else hi = mid;
35
+ }
36
+ return lo;
37
+ }
38
+
39
+ // Similar to bisectLeft, but returns an insertion point which comes after (to
40
+ // the right of) any existing entries of x in a.
41
+ //
42
+ // The returned insertion point i partitions the array into two halves so that
43
+ // all v <= x for v in a[lo:i] for the left side and all v > x for v in
44
+ // a[i:hi] for the right side.
45
+ function bisectRight(a, x, lo, hi) {
46
+ while (lo < hi) {
47
+ var mid = lo + hi >>> 1;
48
+ if (x < f(a[mid])) hi = mid;
49
+ else lo = mid + 1;
50
+ }
51
+ return lo;
52
+ }
53
+
54
+ bisectRight.right = bisectRight;
55
+ bisectRight.left = bisectLeft;
56
+ return bisectRight;
57
+ }
58
+ var heap = crossfilter.heap = heap_by(crossfilter_identity);
59
+
60
+ heap.by = heap_by;
61
+
62
+ function heap_by(f) {
63
+
64
+ // Builds a binary heap within the specified array a[lo:hi]. The heap has the
65
+ // property such that the parent a[lo+i] is always less than or equal to its
66
+ // two children: a[lo+2*i+1] and a[lo+2*i+2].
67
+ function heap(a, lo, hi) {
68
+ var n = hi - lo,
69
+ i = (n >>> 1) + 1;
70
+ while (--i > 0) sift(a, i, n, lo);
71
+ return a;
72
+ }
73
+
74
+ // Sorts the specified array a[lo:hi] in descending order, assuming it is
75
+ // already a heap.
76
+ function sort(a, lo, hi) {
77
+ var n = hi - lo,
78
+ t;
79
+ while (--n > 0) t = a[lo], a[lo] = a[lo + n], a[lo + n] = t, sift(a, 1, n, lo);
80
+ return a;
81
+ }
82
+
83
+ // Sifts the element a[lo+i-1] down the heap, where the heap is the contiguous
84
+ // slice of array a[lo:lo+n]. This method can also be used to update the heap
85
+ // incrementally, without incurring the full cost of reconstructing the heap.
86
+ function sift(a, i, n, lo) {
87
+ var d = a[--lo + i],
88
+ x = f(d),
89
+ child;
90
+ while ((child = i << 1) <= n) {
91
+ if (child < n && f(a[lo + child]) > f(a[lo + child + 1])) child++;
92
+ if (x <= f(a[lo + child])) break;
93
+ a[lo + i] = a[lo + child];
94
+ i = child;
95
+ }
96
+ a[lo + i] = d;
97
+ }
98
+
99
+ heap.sort = sort;
100
+ return heap;
101
+ }
102
+ var heapselect = crossfilter.heapselect = heapselect_by(crossfilter_identity);
103
+
104
+ heapselect.by = heapselect_by;
105
+
106
+ function heapselect_by(f) {
107
+ var heap = heap_by(f);
108
+
109
+ // Returns a new array containing the top k elements in the array a[lo:hi].
110
+ // The returned array is not sorted, but maintains the heap property. If k is
111
+ // greater than hi - lo, then fewer than k elements will be returned. The
112
+ // order of elements in a is unchanged by this operation.
113
+ function heapselect(a, lo, hi, k) {
114
+ var queue = new Array(k = Math.min(hi - lo, k)),
115
+ min,
116
+ i,
117
+ x,
118
+ d;
119
+
120
+ for (i = 0; i < k; ++i) queue[i] = a[lo++];
121
+ heap(queue, 0, k);
122
+
123
+ if (lo < hi) {
124
+ min = f(queue[0]);
125
+ do {
126
+ if (x = f(d = a[lo]) > min) {
127
+ queue[0] = d;
128
+ min = f(heap(queue, 0, k)[0]);
129
+ }
130
+ } while (++lo < hi);
131
+ }
132
+
133
+ return queue;
134
+ }
135
+
136
+ return heapselect;
137
+ }
138
+ var insertionsort = crossfilter.insertionsort = insertionsort_by(crossfilter_identity);
139
+
140
+ insertionsort.by = insertionsort_by;
141
+
142
+ function insertionsort_by(f) {
143
+
144
+ function insertionsort(a, lo, hi) {
145
+ for (var i = lo + 1; i < hi; ++i) {
146
+ for (var j = i, t = a[i], x = f(t); j > lo && f(a[j - 1]) > x; --j) {
147
+ a[j] = a[j - 1];
148
+ }
149
+ a[j] = t;
150
+ }
151
+ return a;
152
+ }
153
+
154
+ return insertionsort;
155
+ }
156
+ // Algorithm designed by Vladimir Yaroslavskiy.
157
+ // Implementation based on the Dart project; see lib/dart/LICENSE for details.
158
+
159
+ var quicksort = crossfilter.quicksort = quicksort_by(crossfilter_identity);
160
+
161
+ quicksort.by = quicksort_by;
162
+
163
+ function quicksort_by(f) {
164
+ var insertionsort = insertionsort_by(f);
165
+
166
+ function sort(a, lo, hi) {
167
+ return (hi - lo < quicksort_sizeThreshold
168
+ ? insertionsort
169
+ : quicksort)(a, lo, hi);
170
+ }
171
+
172
+ function quicksort(a, lo, hi) {
173
+ // Compute the two pivots by looking at 5 elements.
174
+ var sixth = (hi - lo) / 6 | 0,
175
+ i1 = lo + sixth,
176
+ i5 = hi - 1 - sixth,
177
+ i3 = lo + hi - 1 >> 1, // The midpoint.
178
+ i2 = i3 - sixth,
179
+ i4 = i3 + sixth;
180
+
181
+ var e1 = a[i1], x1 = f(e1),
182
+ e2 = a[i2], x2 = f(e2),
183
+ e3 = a[i3], x3 = f(e3),
184
+ e4 = a[i4], x4 = f(e4),
185
+ e5 = a[i5], x5 = f(e5);
186
+
187
+ var t;
188
+
189
+ // Sort the selected 5 elements using a sorting network.
190
+ if (x1 > x2) t = e1, e1 = e2, e2 = t, t = x1, x1 = x2, x2 = t;
191
+ if (x4 > x5) t = e4, e4 = e5, e5 = t, t = x4, x4 = x5, x5 = t;
192
+ if (x1 > x3) t = e1, e1 = e3, e3 = t, t = x1, x1 = x3, x3 = t;
193
+ if (x2 > x3) t = e2, e2 = e3, e3 = t, t = x2, x2 = x3, x3 = t;
194
+ if (x1 > x4) t = e1, e1 = e4, e4 = t, t = x1, x1 = x4, x4 = t;
195
+ if (x3 > x4) t = e3, e3 = e4, e4 = t, t = x3, x3 = x4, x4 = t;
196
+ if (x2 > x5) t = e2, e2 = e5, e5 = t, t = x2, x2 = x5, x5 = t;
197
+ if (x2 > x3) t = e2, e2 = e3, e3 = t, t = x2, x2 = x3, x3 = t;
198
+ if (x4 > x5) t = e4, e4 = e5, e5 = t, t = x4, x4 = x5, x5 = t;
199
+
200
+ var pivot1 = e2, pivotValue1 = x2,
201
+ pivot2 = e4, pivotValue2 = x4;
202
+
203
+ // e2 and e4 have been saved in the pivot variables. They will be written
204
+ // back, once the partitioning is finished.
205
+ a[i1] = e1;
206
+ a[i2] = a[lo];
207
+ a[i3] = e3;
208
+ a[i4] = a[hi - 1];
209
+ a[i5] = e5;
210
+
211
+ var less = lo + 1, // First element in the middle partition.
212
+ great = hi - 2; // Last element in the middle partition.
213
+
214
+ // Note that for value comparison, <, <=, >= and > coerce to a primitive via
215
+ // Object.prototype.valueOf; == and === do not, so in order to be consistent
216
+ // with natural order (such as for Date objects), we must do two compares.
217
+ var pivotsEqual = pivotValue1 <= pivotValue2 && pivotValue1 >= pivotValue2;
218
+ if (pivotsEqual) {
219
+
220
+ // Degenerated case where the partitioning becomes a dutch national flag
221
+ // problem.
222
+ //
223
+ // [ | < pivot | == pivot | unpartitioned | > pivot | ]
224
+ // ^ ^ ^ ^ ^
225
+ // left less k great right
226
+ //
227
+ // a[left] and a[right] are undefined and are filled after the
228
+ // partitioning.
229
+ //
230
+ // Invariants:
231
+ // 1) for x in ]left, less[ : x < pivot.
232
+ // 2) for x in [less, k[ : x == pivot.
233
+ // 3) for x in ]great, right[ : x > pivot.
234
+ for (var k = less; k <= great; ++k) {
235
+ var ek = a[k], xk = f(ek);
236
+ if (xk < pivotValue1) {
237
+ if (k !== less) {
238
+ a[k] = a[less];
239
+ a[less] = ek;
240
+ }
241
+ ++less;
242
+ } else if (xk > pivotValue1) {
243
+
244
+ // Find the first element <= pivot in the range [k - 1, great] and
245
+ // put [:ek:] there. We know that such an element must exist:
246
+ // When k == less, then el3 (which is equal to pivot) lies in the
247
+ // interval. Otherwise a[k - 1] == pivot and the search stops at k-1.
248
+ // Note that in the latter case invariant 2 will be violated for a
249
+ // short amount of time. The invariant will be restored when the
250
+ // pivots are put into their final positions.
251
+ while (true) {
252
+ var greatValue = f(a[great]);
253
+ if (greatValue > pivotValue1) {
254
+ great--;
255
+ // This is the only location in the while-loop where a new
256
+ // iteration is started.
257
+ continue;
258
+ } else if (greatValue < pivotValue1) {
259
+ // Triple exchange.
260
+ a[k] = a[less];
261
+ a[less++] = a[great];
262
+ a[great--] = ek;
263
+ break;
264
+ } else {
265
+ a[k] = a[great];
266
+ a[great--] = ek;
267
+ // Note: if great < k then we will exit the outer loop and fix
268
+ // invariant 2 (which we just violated).
269
+ break;
270
+ }
271
+ }
272
+ }
273
+ }
274
+ } else {
275
+
276
+ // We partition the list into three parts:
277
+ // 1. < pivot1
278
+ // 2. >= pivot1 && <= pivot2
279
+ // 3. > pivot2
280
+ //
281
+ // During the loop we have:
282
+ // [ | < pivot1 | >= pivot1 && <= pivot2 | unpartitioned | > pivot2 | ]
283
+ // ^ ^ ^ ^ ^
284
+ // left less k great right
285
+ //
286
+ // a[left] and a[right] are undefined and are filled after the
287
+ // partitioning.
288
+ //
289
+ // Invariants:
290
+ // 1. for x in ]left, less[ : x < pivot1
291
+ // 2. for x in [less, k[ : pivot1 <= x && x <= pivot2
292
+ // 3. for x in ]great, right[ : x > pivot2
293
+ for (var k = less; k <= great; k++) {
294
+ var ek = a[k], xk = f(ek);
295
+ if (xk < pivotValue1) {
296
+ if (k !== less) {
297
+ a[k] = a[less];
298
+ a[less] = ek;
299
+ }
300
+ ++less;
301
+ } else {
302
+ if (xk > pivotValue2) {
303
+ while (true) {
304
+ var greatValue = f(a[great]);
305
+ if (greatValue > pivotValue2) {
306
+ great--;
307
+ if (great < k) break;
308
+ // This is the only location inside the loop where a new
309
+ // iteration is started.
310
+ continue;
311
+ } else {
312
+ // a[great] <= pivot2.
313
+ if (greatValue < pivotValue1) {
314
+ // Triple exchange.
315
+ a[k] = a[less];
316
+ a[less++] = a[great];
317
+ a[great--] = ek;
318
+ } else {
319
+ // a[great] >= pivot1.
320
+ a[k] = a[great];
321
+ a[great--] = ek;
322
+ }
323
+ break;
324
+ }
325
+ }
326
+ }
327
+ }
328
+ }
329
+ }
330
+
331
+ // Move pivots into their final positions.
332
+ // We shrunk the list from both sides (a[left] and a[right] have
333
+ // meaningless values in them) and now we move elements from the first
334
+ // and third partition into these locations so that we can store the
335
+ // pivots.
336
+ a[lo] = a[less - 1];
337
+ a[less - 1] = pivot1;
338
+ a[hi - 1] = a[great + 1];
339
+ a[great + 1] = pivot2;
340
+
341
+ // The list is now partitioned into three partitions:
342
+ // [ < pivot1 | >= pivot1 && <= pivot2 | > pivot2 ]
343
+ // ^ ^ ^ ^
344
+ // left less great right
345
+
346
+ // Recursive descent. (Don't include the pivot values.)
347
+ sort(a, lo, less - 1);
348
+ sort(a, great + 2, hi);
349
+
350
+ if (pivotsEqual) {
351
+ // All elements in the second partition are equal to the pivot. No
352
+ // need to sort them.
353
+ return a;
354
+ }
355
+
356
+ // In theory it should be enough to call _doSort recursively on the second
357
+ // partition.
358
+ // The Android source however removes the pivot elements from the recursive
359
+ // call if the second partition is too large (more than 2/3 of the list).
360
+ if (less < i1 && great > i5) {
361
+ var lessValue, greatValue;
362
+ while ((lessValue = f(a[less])) <= pivotValue1 && lessValue >= pivotValue1) ++less;
363
+ while ((greatValue = f(a[great])) <= pivotValue2 && greatValue >= pivotValue2) --great;
364
+
365
+ // Copy paste of the previous 3-way partitioning with adaptions.
366
+ //
367
+ // We partition the list into three parts:
368
+ // 1. == pivot1
369
+ // 2. > pivot1 && < pivot2
370
+ // 3. == pivot2
371
+ //
372
+ // During the loop we have:
373
+ // [ == pivot1 | > pivot1 && < pivot2 | unpartitioned | == pivot2 ]
374
+ // ^ ^ ^
375
+ // less k great
376
+ //
377
+ // Invariants:
378
+ // 1. for x in [ *, less[ : x == pivot1
379
+ // 2. for x in [less, k[ : pivot1 < x && x < pivot2
380
+ // 3. for x in ]great, * ] : x == pivot2
381
+ for (var k = less; k <= great; k++) {
382
+ var ek = a[k], xk = f(ek);
383
+ if (xk <= pivotValue1 && xk >= pivotValue1) {
384
+ if (k !== less) {
385
+ a[k] = a[less];
386
+ a[less] = ek;
387
+ }
388
+ less++;
389
+ } else {
390
+ if (xk <= pivotValue2 && xk >= pivotValue2) {
391
+ while (true) {
392
+ var greatValue = f(a[great]);
393
+ if (greatValue <= pivotValue2 && greatValue >= pivotValue2) {
394
+ great--;
395
+ if (great < k) break;
396
+ // This is the only location inside the loop where a new
397
+ // iteration is started.
398
+ continue;
399
+ } else {
400
+ // a[great] < pivot2.
401
+ if (greatValue < pivotValue1) {
402
+ // Triple exchange.
403
+ a[k] = a[less];
404
+ a[less++] = a[great];
405
+ a[great--] = ek;
406
+ } else {
407
+ // a[great] == pivot1.
408
+ a[k] = a[great];
409
+ a[great--] = ek;
410
+ }
411
+ break;
412
+ }
413
+ }
414
+ }
415
+ }
416
+ }
417
+ }
418
+
419
+ // The second partition has now been cleared of pivot elements and looks
420
+ // as follows:
421
+ // [ * | > pivot1 && < pivot2 | * ]
422
+ // ^ ^
423
+ // less great
424
+ // Sort the second partition using recursive descent.
425
+
426
+ // The second partition looks as follows:
427
+ // [ * | >= pivot1 && <= pivot2 | * ]
428
+ // ^ ^
429
+ // less great
430
+ // Simply sort it by recursive descent.
431
+
432
+ return sort(a, less, great + 1);
433
+ }
434
+
435
+ return sort;
436
+ }
437
+
438
+ var quicksort_sizeThreshold = 32;
439
+ var crossfilter_array8 = crossfilter_arrayUntyped,
440
+ crossfilter_array16 = crossfilter_arrayUntyped,
441
+ crossfilter_array32 = crossfilter_arrayUntyped,
442
+ crossfilter_arrayLengthen = crossfilter_identity,
443
+ crossfilter_arrayWiden = crossfilter_identity;
444
+
445
+ if (typeof Uint8Array !== "undefined") {
446
+ crossfilter_array8 = function(n) { return new Uint8Array(n); };
447
+ crossfilter_array16 = function(n) { return new Uint16Array(n); };
448
+ crossfilter_array32 = function(n) { return new Uint32Array(n); };
449
+
450
+ crossfilter_arrayLengthen = function(array, length) {
451
+ if (array.length >= length) return array;
452
+ var copy = new array.constructor(length);
453
+ copy.set(array);
454
+ return copy;
455
+ };
456
+
457
+ crossfilter_arrayWiden = function(array, width) {
458
+ var copy;
459
+ switch (width) {
460
+ case 16: copy = crossfilter_array16(array.length); break;
461
+ case 32: copy = crossfilter_array32(array.length); break;
462
+ default: throw new Error("invalid array width!");
463
+ }
464
+ copy.set(array);
465
+ return copy;
466
+ };
467
+ }
468
+
469
+ function crossfilter_arrayUntyped(n) {
470
+ return new Array(n);
471
+ }
472
+ function crossfilter_filterExact(bisect, value) {
473
+ return function(values) {
474
+ var n = values.length;
475
+ return [bisect.left(values, value, 0, n), bisect.right(values, value, 0, n)];
476
+ };
477
+ }
478
+
479
+ function crossfilter_filterRange(bisect, range) {
480
+ var min = range[0],
481
+ max = range[1];
482
+ return function(values) {
483
+ var n = values.length;
484
+ return [bisect.left(values, min, 0, n), bisect.left(values, max, 0, n)];
485
+ };
486
+ }
487
+
488
+ function crossfilter_filterAll(values) {
489
+ return [0, values.length];
490
+ }
491
+ function crossfilter_null() {
492
+ return null;
493
+ }
494
+ function crossfilter_zero() {
495
+ return 0;
496
+ }
497
+ function crossfilter_reduceIncrement(p) {
498
+ return p + 1;
499
+ }
500
+
501
+ function crossfilter_reduceDecrement(p) {
502
+ return p - 1;
503
+ }
504
+
505
+ function crossfilter_reduceAdd(f) {
506
+ return function(p, v) {
507
+ return p + +f(v);
508
+ };
509
+ }
510
+
511
+ function crossfilter_reduceSubtract(f) {
512
+ return function(p, v) {
513
+ return p - f(v);
514
+ };
515
+ }
516
+ exports.crossfilter = crossfilter;
517
+
518
+ function crossfilter() {
519
+ var crossfilter = {
520
+ add: add,
521
+ remove: removeData,
522
+ dimension: dimension,
523
+ groupAll: groupAll,
524
+ size: size
525
+ };
526
+
527
+ var data = [], // the records
528
+ n = 0, // the number of records; data.length
529
+ m = 0, // a bit mask representing which dimensions are in use
530
+ M = 8, // number of dimensions that can fit in `filters`
531
+ filters = crossfilter_array8(0), // M bits per record; 1 is filtered out
532
+ filterListeners = [], // when the filters change
533
+ dataListeners = [], // when data is added
534
+ removeDataListeners = []; // when data is removed
535
+
536
+ // Adds the specified new records to this crossfilter.
537
+ function add(newData) {
538
+ var n0 = n,
539
+ n1 = newData.length;
540
+
541
+ // If there's actually new data to add…
542
+ // Merge the new data into the existing data.
543
+ // Lengthen the filter bitset to handle the new records.
544
+ // Notify listeners (dimensions and groups) that new data is available.
545
+ if (n1) {
546
+ data = data.concat(newData);
547
+ filters = crossfilter_arrayLengthen(filters, n += n1);
548
+ dataListeners.forEach(function(l) { l(newData, n0, n1); });
549
+ }
550
+
551
+ return crossfilter;
552
+ }
553
+
554
+ // Removes all records that match the current filters.
555
+ function removeData() {
556
+ var newIndex = crossfilter_index(n, n),
557
+ removed = [];
558
+ for (var i = 0, j = 0; i < n; ++i) {
559
+ if (filters[i]) newIndex[i] = j++;
560
+ else removed.push(i);
561
+ }
562
+
563
+ // Remove all matching records from groups.
564
+ filterListeners.forEach(function(l) { l(0, [], removed); });
565
+
566
+ // Update indexes.
567
+ removeDataListeners.forEach(function(l) { l(newIndex); });
568
+
569
+ // Remove old filters and data by overwriting.
570
+ for (var i = 0, j = 0, k; i < n; ++i) {
571
+ if (k = filters[i]) {
572
+ if (i !== j) filters[j] = k, data[j] = data[i];
573
+ ++j;
574
+ }
575
+ }
576
+ data.length = j;
577
+ while (n > j) filters[--n] = 0;
578
+ }
579
+
580
+ // Adds a new dimension with the specified value accessor function.
581
+ function dimension(value) {
582
+ var dimension = {
583
+ filter: filter,
584
+ filterExact: filterExact,
585
+ filterRange: filterRange,
586
+ filterFunction: filterFunction,
587
+ filterAll: filterAll,
588
+ top: top,
589
+ bottom: bottom,
590
+ group: group,
591
+ groupAll: groupAll,
592
+ dispose: dispose,
593
+ remove: dispose // for backwards-compatibility
594
+ };
595
+
596
+ var one = ~m & -~m, // lowest unset bit as mask, e.g., 00001000
597
+ zero = ~one, // inverted one, e.g., 11110111
598
+ values, // sorted, cached array
599
+ index, // value rank ↦ object id
600
+ newValues, // temporary array storing newly-added values
601
+ newIndex, // temporary array storing newly-added index
602
+ sort = quicksort_by(function(i) { return newValues[i]; }),
603
+ refilter = crossfilter_filterAll, // for recomputing filter
604
+ refilterFunction, // the custom filter function in use
605
+ indexListeners = [], // when data is added
606
+ dimensionGroups = [],
607
+ lo0 = 0,
608
+ hi0 = 0;
609
+
610
+ // Updating a dimension is a two-stage process. First, we must update the
611
+ // associated filters for the newly-added records. Once all dimensions have
612
+ // updated their filters, the groups are notified to update.
613
+ dataListeners.unshift(preAdd);
614
+ dataListeners.push(postAdd);
615
+
616
+ removeDataListeners.push(removeData);
617
+
618
+ // Incorporate any existing data into this dimension, and make sure that the
619
+ // filter bitset is wide enough to handle the new dimension.
620
+ m |= one;
621
+ if (M >= 32 ? !one : m & (1 << M) - 1) {
622
+ filters = crossfilter_arrayWiden(filters, M <<= 1);
623
+ }
624
+ preAdd(data, 0, n);
625
+ postAdd(data, 0, n);
626
+
627
+ // Incorporates the specified new records into this dimension.
628
+ // This function is responsible for updating filters, values, and index.
629
+ function preAdd(newData, n0, n1) {
630
+
631
+ // Permute new values into natural order using a sorted index.
632
+ newValues = newData.map(value);
633
+ newIndex = sort(crossfilter_range(n1), 0, n1);
634
+ newValues = permute(newValues, newIndex);
635
+
636
+ // Bisect newValues to determine which new records are selected.
637
+ var bounds = refilter(newValues), lo1 = bounds[0], hi1 = bounds[1], i;
638
+ if (refilterFunction) {
639
+ for (i = 0; i < n1; ++i) {
640
+ if (!refilterFunction(newValues[i], i)) filters[newIndex[i] + n0] |= one;
641
+ }
642
+ } else {
643
+ for (i = 0; i < lo1; ++i) filters[newIndex[i] + n0] |= one;
644
+ for (i = hi1; i < n1; ++i) filters[newIndex[i] + n0] |= one;
645
+ }
646
+
647
+ // If this dimension previously had no data, then we don't need to do the
648
+ // more expensive merge operation; use the new values and index as-is.
649
+ if (!n0) {
650
+ values = newValues;
651
+ index = newIndex;
652
+ lo0 = lo1;
653
+ hi0 = hi1;
654
+ return;
655
+ }
656
+
657
+ var oldValues = values,
658
+ oldIndex = index,
659
+ i0 = 0,
660
+ i1 = 0;
661
+
662
+ // Otherwise, create new arrays into which to merge new and old.
663
+ values = new Array(n);
664
+ index = crossfilter_index(n, n);
665
+
666
+ // Merge the old and new sorted values, and old and new index.
667
+ for (i = 0; i0 < n0 && i1 < n1; ++i) {
668
+ if (oldValues[i0] < newValues[i1]) {
669
+ values[i] = oldValues[i0];
670
+ index[i] = oldIndex[i0++];
671
+ } else {
672
+ values[i] = newValues[i1];
673
+ index[i] = newIndex[i1++] + n0;
674
+ }
675
+ }
676
+
677
+ // Add any remaining old values.
678
+ for (; i0 < n0; ++i0, ++i) {
679
+ values[i] = oldValues[i0];
680
+ index[i] = oldIndex[i0];
681
+ }
682
+
683
+ // Add any remaining new values.
684
+ for (; i1 < n1; ++i1, ++i) {
685
+ values[i] = newValues[i1];
686
+ index[i] = newIndex[i1] + n0;
687
+ }
688
+
689
+ // Bisect again to recompute lo0 and hi0.
690
+ bounds = refilter(values), lo0 = bounds[0], hi0 = bounds[1];
691
+ }
692
+
693
+ // When all filters have updated, notify index listeners of the new values.
694
+ function postAdd(newData, n0, n1) {
695
+ indexListeners.forEach(function(l) { l(newValues, newIndex, n0, n1); });
696
+ newValues = newIndex = null;
697
+ }
698
+
699
+ function removeData(reIndex) {
700
+ for (var i = 0, j = 0, k; i < n; ++i) {
701
+ if (filters[k = index[i]]) {
702
+ if (i !== j) values[j] = values[i];
703
+ index[j] = reIndex[k];
704
+ ++j;
705
+ }
706
+ }
707
+ values.length = j;
708
+ while (j < n) index[j++] = 0;
709
+
710
+ // Bisect again to recompute lo0 and hi0.
711
+ var bounds = refilter(values);
712
+ lo0 = bounds[0], hi0 = bounds[1];
713
+ }
714
+
715
+ // Updates the selected values based on the specified bounds [lo, hi].
716
+ // This implementation is used by all the public filter methods.
717
+ function filterIndexBounds(bounds) {
718
+ var lo1 = bounds[0],
719
+ hi1 = bounds[1];
720
+
721
+ if (refilterFunction) {
722
+ refilterFunction = null;
723
+ filterIndexFunction(function(d, i) { return lo1 <= i && i < hi1; });
724
+ lo0 = lo1;
725
+ hi0 = hi1;
726
+ return dimension;
727
+ }
728
+
729
+ var i,
730
+ j,
731
+ k,
732
+ added = [],
733
+ removed = [];
734
+
735
+ // Fast incremental update based on previous lo index.
736
+ if (lo1 < lo0) {
737
+ for (i = lo1, j = Math.min(lo0, hi1); i < j; ++i) {
738
+ filters[k = index[i]] ^= one;
739
+ added.push(k);
740
+ }
741
+ } else if (lo1 > lo0) {
742
+ for (i = lo0, j = Math.min(lo1, hi0); i < j; ++i) {
743
+ filters[k = index[i]] ^= one;
744
+ removed.push(k);
745
+ }
746
+ }
747
+
748
+ // Fast incremental update based on previous hi index.
749
+ if (hi1 > hi0) {
750
+ for (i = Math.max(lo1, hi0), j = hi1; i < j; ++i) {
751
+ filters[k = index[i]] ^= one;
752
+ added.push(k);
753
+ }
754
+ } else if (hi1 < hi0) {
755
+ for (i = Math.max(lo0, hi1), j = hi0; i < j; ++i) {
756
+ filters[k = index[i]] ^= one;
757
+ removed.push(k);
758
+ }
759
+ }
760
+
761
+ lo0 = lo1;
762
+ hi0 = hi1;
763
+ filterListeners.forEach(function(l) { l(one, added, removed); });
764
+ return dimension;
765
+ }
766
+
767
+ // Filters this dimension using the specified range, value, or null.
768
+ // If the range is null, this is equivalent to filterAll.
769
+ // If the range is an array, this is equivalent to filterRange.
770
+ // Otherwise, this is equivalent to filterExact.
771
+ function filter(range) {
772
+ return range == null
773
+ ? filterAll() : Array.isArray(range)
774
+ ? filterRange(range) : typeof range === "function"
775
+ ? filterFunction(range)
776
+ : filterExact(range);
777
+ }
778
+
779
+ // Filters this dimension to select the exact value.
780
+ function filterExact(value) {
781
+ return filterIndexBounds((refilter = crossfilter_filterExact(bisect, value))(values));
782
+ }
783
+
784
+ // Filters this dimension to select the specified range [lo, hi].
785
+ // The lower bound is inclusive, and the upper bound is exclusive.
786
+ function filterRange(range) {
787
+ return filterIndexBounds((refilter = crossfilter_filterRange(bisect, range))(values));
788
+ }
789
+
790
+ // Clears any filters on this dimension.
791
+ function filterAll() {
792
+ return filterIndexBounds((refilter = crossfilter_filterAll)(values));
793
+ }
794
+
795
+ // Filters this dimension using an arbitrary function.
796
+ function filterFunction(f) {
797
+ refilter = crossfilter_filterAll;
798
+
799
+ filterIndexFunction(refilterFunction = f);
800
+
801
+ lo0 = 0;
802
+ hi0 = n;
803
+
804
+ return dimension;
805
+ }
806
+
807
+ function filterIndexFunction(f) {
808
+ var i,
809
+ k,
810
+ x,
811
+ added = [],
812
+ removed = [];
813
+
814
+ for (i = 0; i < n; ++i) {
815
+ if (!(filters[k = index[i]] & one) ^ (x = f(values[i], i))) {
816
+ if (x) filters[k] &= zero, added.push(k);
817
+ else filters[k] |= one, removed.push(k);
818
+ }
819
+ }
820
+ filterListeners.forEach(function(l) { l(one, added, removed); });
821
+ }
822
+
823
+ // Returns the top K selected records based on this dimension's order.
824
+ // Note: observes this dimension's filter, unlike group and groupAll.
825
+ function top(k) {
826
+ var array = [],
827
+ i = hi0,
828
+ j;
829
+
830
+ while (--i >= lo0 && k > 0) {
831
+ if (!filters[j = index[i]]) {
832
+ array.push(data[j]);
833
+ --k;
834
+ }
835
+ }
836
+
837
+ return array;
838
+ }
839
+
840
+ // Returns the bottom K selected records based on this dimension's order.
841
+ // Note: observes this dimension's filter, unlike group and groupAll.
842
+ function bottom(k) {
843
+ var array = [],
844
+ i = lo0,
845
+ j;
846
+
847
+ while (i < hi0 && k > 0) {
848
+ if (!filters[j = index[i]]) {
849
+ array.push(data[j]);
850
+ --k;
851
+ }
852
+ i++;
853
+ }
854
+
855
+ return array;
856
+ }
857
+
858
+ // Adds a new group to this dimension, using the specified key function.
859
+ function group(key) {
860
+ var group = {
861
+ top: top,
862
+ all: all,
863
+ reduce: reduce,
864
+ reduceCount: reduceCount,
865
+ reduceSum: reduceSum,
866
+ order: order,
867
+ orderNatural: orderNatural,
868
+ size: size,
869
+ dispose: dispose,
870
+ remove: dispose // for backwards-compatibility
871
+ };
872
+
873
+ // Ensure that this group will be removed when the dimension is removed.
874
+ dimensionGroups.push(group);
875
+
876
+ var groups, // array of {key, value}
877
+ groupIndex, // object id ↦ group id
878
+ groupWidth = 8,
879
+ groupCapacity = crossfilter_capacity(groupWidth),
880
+ k = 0, // cardinality
881
+ select,
882
+ heap,
883
+ reduceAdd,
884
+ reduceRemove,
885
+ reduceInitial,
886
+ update = crossfilter_null,
887
+ reset = crossfilter_null,
888
+ resetNeeded = true;
889
+
890
+ if (arguments.length < 1) key = crossfilter_identity;
891
+
892
+ // The group listens to the crossfilter for when any dimension changes, so
893
+ // that it can update the associated reduce values. It must also listen to
894
+ // the parent dimension for when data is added, and compute new keys.
895
+ filterListeners.push(update);
896
+ indexListeners.push(add);
897
+ removeDataListeners.push(removeData);
898
+
899
+ // Incorporate any existing data into the grouping.
900
+ add(values, index, 0, n);
901
+
902
+ // Incorporates the specified new values into this group.
903
+ // This function is responsible for updating groups and groupIndex.
904
+ function add(newValues, newIndex, n0, n1) {
905
+ var oldGroups = groups,
906
+ reIndex = crossfilter_index(k, groupCapacity),
907
+ add = reduceAdd,
908
+ initial = reduceInitial,
909
+ k0 = k, // old cardinality
910
+ i0 = 0, // index of old group
911
+ i1 = 0, // index of new record
912
+ j, // object id
913
+ g0, // old group
914
+ x0, // old key
915
+ x1, // new key
916
+ g, // group to add
917
+ x; // key of group to add
918
+
919
+ // If a reset is needed, we don't need to update the reduce values.
920
+ if (resetNeeded) add = initial = crossfilter_null;
921
+
922
+ // Reset the new groups (k is a lower bound).
923
+ // Also, make sure that groupIndex exists and is long enough.
924
+ groups = new Array(k), k = 0;
925
+ groupIndex = k0 > 1 ? crossfilter_arrayLengthen(groupIndex, n) : crossfilter_index(n, groupCapacity);
926
+
927
+ // Get the first old key (x0 of g0), if it exists.
928
+ if (k0) x0 = (g0 = oldGroups[0]).key;
929
+
930
+ // Find the first new key (x1), skipping NaN keys.
931
+ while (i1 < n1 && !((x1 = key(newValues[i1])) >= x1)) ++i1;
932
+
933
+ // While new keys remain…
934
+ while (i1 < n1) {
935
+
936
+ // Determine the lesser of the two current keys; new and old.
937
+ // If there are no old keys remaining, then always add the new key.
938
+ if (g0 && x0 <= x1) {
939
+ g = g0, x = x0;
940
+
941
+ // Record the new index of the old group.
942
+ reIndex[i0] = k;
943
+
944
+ // Retrieve the next old key.
945
+ if (g0 = oldGroups[++i0]) x0 = g0.key;
946
+ } else {
947
+ g = {key: x1, value: initial()}, x = x1;
948
+ }
949
+
950
+ // Add the lesser group.
951
+ groups[k] = g;
952
+
953
+ // Add any selected records belonging to the added group, while
954
+ // advancing the new key and populating the associated group index.
955
+ while (!(x1 > x)) {
956
+ groupIndex[j = newIndex[i1] + n0] = k;
957
+ if (!(filters[j] & zero)) g.value = add(g.value, data[j]);
958
+ if (++i1 >= n1) break;
959
+ x1 = key(newValues[i1]);
960
+ }
961
+
962
+ groupIncrement();
963
+ }
964
+
965
+ // Add any remaining old groups that were greater than all new keys.
966
+ // No incremental reduce is needed; these groups have no new records.
967
+ // Also record the new index of the old group.
968
+ while (i0 < k0) {
969
+ groups[reIndex[i0] = k] = oldGroups[i0++];
970
+ groupIncrement();
971
+ }
972
+
973
+ // If we added any new groups before any old groups,
974
+ // update the group index of all the old records.
975
+ if (k > i0) for (i0 = 0; i0 < n0; ++i0) {
976
+ groupIndex[i0] = reIndex[groupIndex[i0]];
977
+ }
978
+
979
+ // Modify the update and reset behavior based on the cardinality.
980
+ // If the cardinality is less than or equal to one, then the groupIndex
981
+ // is not needed. If the cardinality is zero, then there are no records
982
+ // and therefore no groups to update or reset. Note that we also must
983
+ // change the registered listener to point to the new method.
984
+ j = filterListeners.indexOf(update);
985
+ if (k > 1) {
986
+ update = updateMany;
987
+ reset = resetMany;
988
+ } else {
989
+ if (k === 1) {
990
+ update = updateOne;
991
+ reset = resetOne;
992
+ } else {
993
+ update = crossfilter_null;
994
+ reset = crossfilter_null;
995
+ }
996
+ groupIndex = null;
997
+ }
998
+ filterListeners[j] = update;
999
+
1000
+ // Count the number of added groups,
1001
+ // and widen the group index as needed.
1002
+ function groupIncrement() {
1003
+ if (++k === groupCapacity) {
1004
+ reIndex = crossfilter_arrayWiden(reIndex, groupWidth <<= 1);
1005
+ groupIndex = crossfilter_arrayWiden(groupIndex, groupWidth);
1006
+ groupCapacity = crossfilter_capacity(groupWidth);
1007
+ }
1008
+ }
1009
+ }
1010
+
1011
+ function removeData() {
1012
+ if (k > 1) {
1013
+ var oldK = k,
1014
+ oldGroups = groups,
1015
+ seenGroups = crossfilter_index(oldK, oldK);
1016
+
1017
+ // Filter out non-matches by copying matching group index entries to
1018
+ // the beginning of the array.
1019
+ for (var i = 0, j = 0; i < n; ++i) {
1020
+ if (filters[i]) {
1021
+ seenGroups[groupIndex[j] = groupIndex[i]] = 1;
1022
+ ++j;
1023
+ }
1024
+ }
1025
+
1026
+ // Reassemble groups including only those groups that were referred
1027
+ // to by matching group index entries. Note the new group index in
1028
+ // seenGroups.
1029
+ groups = [], k = 0;
1030
+ for (i = 0; i < oldK; ++i) {
1031
+ if (seenGroups[i]) {
1032
+ seenGroups[i] = k++;
1033
+ groups.push(oldGroups[i]);
1034
+ }
1035
+ }
1036
+
1037
+ if (k > 1) {
1038
+ // Reindex the group index using seenGroups to find the new index.
1039
+ for (var i = 0; i < j; ++i) groupIndex[i] = seenGroups[groupIndex[i]];
1040
+ } else {
1041
+ groupIndex = null;
1042
+ }
1043
+ filterListeners[filterListeners.indexOf(update)] = k > 1
1044
+ ? (reset = resetMany, update = updateMany)
1045
+ : k === 1 ? (reset = resetOne, update = updateOne)
1046
+ : reset = update = crossfilter_null;
1047
+ } else if (k === 1) {
1048
+ for (var i = 0; i < n; ++i) if (filters[i]) return;
1049
+ groups = [], k = 0;
1050
+ filterListeners[filterListeners.indexOf(update)] =
1051
+ update = reset = crossfilter_null;
1052
+ }
1053
+ }
1054
+
1055
+ // Reduces the specified selected or deselected records.
1056
+ // This function is only used when the cardinality is greater than 1.
1057
+ function updateMany(filterOne, added, removed) {
1058
+ if (filterOne === one || resetNeeded) return;
1059
+
1060
+ var i,
1061
+ k,
1062
+ n,
1063
+ g;
1064
+
1065
+ // Add the added values.
1066
+ for (i = 0, n = added.length; i < n; ++i) {
1067
+ if (!(filters[k = added[i]] & zero)) {
1068
+ g = groups[groupIndex[k]];
1069
+ g.value = reduceAdd(g.value, data[k]);
1070
+ }
1071
+ }
1072
+
1073
+ // Remove the removed values.
1074
+ for (i = 0, n = removed.length; i < n; ++i) {
1075
+ if ((filters[k = removed[i]] & zero) === filterOne) {
1076
+ g = groups[groupIndex[k]];
1077
+ g.value = reduceRemove(g.value, data[k]);
1078
+ }
1079
+ }
1080
+ }
1081
+
1082
+ // Reduces the specified selected or deselected records.
1083
+ // This function is only used when the cardinality is 1.
1084
+ function updateOne(filterOne, added, removed) {
1085
+ if (filterOne === one || resetNeeded) return;
1086
+
1087
+ var i,
1088
+ k,
1089
+ n,
1090
+ g = groups[0];
1091
+
1092
+ // Add the added values.
1093
+ for (i = 0, n = added.length; i < n; ++i) {
1094
+ if (!(filters[k = added[i]] & zero)) {
1095
+ g.value = reduceAdd(g.value, data[k]);
1096
+ }
1097
+ }
1098
+
1099
+ // Remove the removed values.
1100
+ for (i = 0, n = removed.length; i < n; ++i) {
1101
+ if ((filters[k = removed[i]] & zero) === filterOne) {
1102
+ g.value = reduceRemove(g.value, data[k]);
1103
+ }
1104
+ }
1105
+ }
1106
+
1107
+ // Recomputes the group reduce values from scratch.
1108
+ // This function is only used when the cardinality is greater than 1.
1109
+ function resetMany() {
1110
+ var i,
1111
+ g;
1112
+
1113
+ // Reset all group values.
1114
+ for (i = 0; i < k; ++i) {
1115
+ groups[i].value = reduceInitial();
1116
+ }
1117
+
1118
+ // Add any selected records.
1119
+ for (i = 0; i < n; ++i) {
1120
+ if (!(filters[i] & zero)) {
1121
+ g = groups[groupIndex[i]];
1122
+ g.value = reduceAdd(g.value, data[i]);
1123
+ }
1124
+ }
1125
+ }
1126
+
1127
+ // Recomputes the group reduce values from scratch.
1128
+ // This function is only used when the cardinality is 1.
1129
+ function resetOne() {
1130
+ var i,
1131
+ g = groups[0];
1132
+
1133
+ // Reset the singleton group values.
1134
+ g.value = reduceInitial();
1135
+
1136
+ // Add any selected records.
1137
+ for (i = 0; i < n; ++i) {
1138
+ if (!(filters[i] & zero)) {
1139
+ g.value = reduceAdd(g.value, data[i]);
1140
+ }
1141
+ }
1142
+ }
1143
+
1144
+ // Returns the array of group values, in the dimension's natural order.
1145
+ function all() {
1146
+ if (resetNeeded) reset(), resetNeeded = false;
1147
+ return groups;
1148
+ }
1149
+
1150
+ // Returns a new array containing the top K group values, in reduce order.
1151
+ function top(k) {
1152
+ var top = select(all(), 0, groups.length, k);
1153
+ return heap.sort(top, 0, top.length);
1154
+ }
1155
+
1156
+ // Sets the reduce behavior for this group to use the specified functions.
1157
+ // This method lazily recomputes the reduce values, waiting until needed.
1158
+ function reduce(add, remove, initial) {
1159
+ reduceAdd = add;
1160
+ reduceRemove = remove;
1161
+ reduceInitial = initial;
1162
+ resetNeeded = true;
1163
+ return group;
1164
+ }
1165
+
1166
+ // A convenience method for reducing by count.
1167
+ function reduceCount() {
1168
+ return reduce(crossfilter_reduceIncrement, crossfilter_reduceDecrement, crossfilter_zero);
1169
+ }
1170
+
1171
+ // A convenience method for reducing by sum(value).
1172
+ function reduceSum(value) {
1173
+ return reduce(crossfilter_reduceAdd(value), crossfilter_reduceSubtract(value), crossfilter_zero);
1174
+ }
1175
+
1176
+ // Sets the reduce order, using the specified accessor.
1177
+ function order(value) {
1178
+ select = heapselect_by(valueOf);
1179
+ heap = heap_by(valueOf);
1180
+ function valueOf(d) { return value(d.value); }
1181
+ return group;
1182
+ }
1183
+
1184
+ // A convenience method for natural ordering by reduce value.
1185
+ function orderNatural() {
1186
+ return order(crossfilter_identity);
1187
+ }
1188
+
1189
+ // Returns the cardinality of this group, irrespective of any filters.
1190
+ function size() {
1191
+ return k;
1192
+ }
1193
+
1194
+ // Removes this group and associated event listeners.
1195
+ function dispose() {
1196
+ var i = filterListeners.indexOf(update);
1197
+ if (i >= 0) filterListeners.splice(i, 1);
1198
+ i = indexListeners.indexOf(add);
1199
+ if (i >= 0) indexListeners.splice(i, 1);
1200
+ i = removeDataListeners.indexOf(removeData);
1201
+ if (i >= 0) removeDataListeners.splice(i, 1);
1202
+ return group;
1203
+ }
1204
+
1205
+ return reduceCount().orderNatural();
1206
+ }
1207
+
1208
+ // A convenience function for generating a singleton group.
1209
+ function groupAll() {
1210
+ var g = group(crossfilter_null), all = g.all;
1211
+ delete g.all;
1212
+ delete g.top;
1213
+ delete g.order;
1214
+ delete g.orderNatural;
1215
+ delete g.size;
1216
+ g.value = function() { return all()[0].value; };
1217
+ return g;
1218
+ }
1219
+
1220
+ // Removes this dimension and associated groups and event listeners.
1221
+ function dispose() {
1222
+ dimensionGroups.forEach(function(group) { group.dispose(); });
1223
+ var i = dataListeners.indexOf(preAdd);
1224
+ if (i >= 0) dataListeners.splice(i, 1);
1225
+ i = dataListeners.indexOf(postAdd);
1226
+ if (i >= 0) dataListeners.splice(i, 1);
1227
+ i = removeDataListeners.indexOf(removeData);
1228
+ if (i >= 0) removeDataListeners.splice(i, 1);
1229
+ for (i = 0; i < n; ++i) filters[i] &= zero;
1230
+ m &= zero;
1231
+ return dimension;
1232
+ }
1233
+
1234
+ return dimension;
1235
+ }
1236
+
1237
+ // A convenience method for groupAll on a dummy dimension.
1238
+ // This implementation can be optimized since it always has cardinality 1.
1239
+ function groupAll() {
1240
+ var group = {
1241
+ reduce: reduce,
1242
+ reduceCount: reduceCount,
1243
+ reduceSum: reduceSum,
1244
+ value: value,
1245
+ dispose: dispose,
1246
+ remove: dispose // for backwards-compatibility
1247
+ };
1248
+
1249
+ var reduceValue,
1250
+ reduceAdd,
1251
+ reduceRemove,
1252
+ reduceInitial,
1253
+ resetNeeded = true;
1254
+
1255
+ // The group listens to the crossfilter for when any dimension changes, so
1256
+ // that it can update the reduce value. It must also listen to the parent
1257
+ // dimension for when data is added.
1258
+ filterListeners.push(update);
1259
+ dataListeners.push(add);
1260
+
1261
+ // For consistency; actually a no-op since resetNeeded is true.
1262
+ add(data, 0, n);
1263
+
1264
+ // Incorporates the specified new values into this group.
1265
+ function add(newData, n0) {
1266
+ var i;
1267
+
1268
+ if (resetNeeded) return;
1269
+
1270
+ // Add the added values.
1271
+ for (i = n0; i < n; ++i) {
1272
+ if (!filters[i]) {
1273
+ reduceValue = reduceAdd(reduceValue, data[i]);
1274
+ }
1275
+ }
1276
+ }
1277
+
1278
+ // Reduces the specified selected or deselected records.
1279
+ function update(filterOne, added, removed) {
1280
+ var i,
1281
+ k,
1282
+ n;
1283
+
1284
+ if (resetNeeded) return;
1285
+
1286
+ // Add the added values.
1287
+ for (i = 0, n = added.length; i < n; ++i) {
1288
+ if (!filters[k = added[i]]) {
1289
+ reduceValue = reduceAdd(reduceValue, data[k]);
1290
+ }
1291
+ }
1292
+
1293
+ // Remove the removed values.
1294
+ for (i = 0, n = removed.length; i < n; ++i) {
1295
+ if (filters[k = removed[i]] === filterOne) {
1296
+ reduceValue = reduceRemove(reduceValue, data[k]);
1297
+ }
1298
+ }
1299
+ }
1300
+
1301
+ // Recomputes the group reduce value from scratch.
1302
+ function reset() {
1303
+ var i;
1304
+
1305
+ reduceValue = reduceInitial();
1306
+
1307
+ for (i = 0; i < n; ++i) {
1308
+ if (!filters[i]) {
1309
+ reduceValue = reduceAdd(reduceValue, data[i]);
1310
+ }
1311
+ }
1312
+ }
1313
+
1314
+ // Sets the reduce behavior for this group to use the specified functions.
1315
+ // This method lazily recomputes the reduce value, waiting until needed.
1316
+ function reduce(add, remove, initial) {
1317
+ reduceAdd = add;
1318
+ reduceRemove = remove;
1319
+ reduceInitial = initial;
1320
+ resetNeeded = true;
1321
+ return group;
1322
+ }
1323
+
1324
+ // A convenience method for reducing by count.
1325
+ function reduceCount() {
1326
+ return reduce(crossfilter_reduceIncrement, crossfilter_reduceDecrement, crossfilter_zero);
1327
+ }
1328
+
1329
+ // A convenience method for reducing by sum(value).
1330
+ function reduceSum(value) {
1331
+ return reduce(crossfilter_reduceAdd(value), crossfilter_reduceSubtract(value), crossfilter_zero);
1332
+ }
1333
+
1334
+ // Returns the computed reduce value.
1335
+ function value() {
1336
+ if (resetNeeded) reset(), resetNeeded = false;
1337
+ return reduceValue;
1338
+ }
1339
+
1340
+ // Removes this group and associated event listeners.
1341
+ function dispose() {
1342
+ var i = filterListeners.indexOf(update);
1343
+ if (i >= 0) filterListeners.splice(i);
1344
+ i = dataListeners.indexOf(add);
1345
+ if (i >= 0) dataListeners.splice(i);
1346
+ return group;
1347
+ }
1348
+
1349
+ return reduceCount();
1350
+ }
1351
+
1352
+ // Returns the number of records in this crossfilter, irrespective of any filters.
1353
+ function size() {
1354
+ return n;
1355
+ }
1356
+
1357
+ return arguments.length
1358
+ ? add(arguments[0])
1359
+ : crossfilter;
1360
+ }
1361
+
1362
+ // Returns an array of size n, big enough to store ids up to m.
1363
+ function crossfilter_index(n, m) {
1364
+ return (m < 0x101
1365
+ ? crossfilter_array8 : m < 0x10001
1366
+ ? crossfilter_array16
1367
+ : crossfilter_array32)(n);
1368
+ }
1369
+
1370
+ // Constructs a new array of size n, with sequential values from 0 to n - 1.
1371
+ function crossfilter_range(n) {
1372
+ var range = crossfilter_index(n, n);
1373
+ for (var i = -1; ++i < n;) range[i] = i;
1374
+ return range;
1375
+ }
1376
+
1377
+ function crossfilter_capacity(w) {
1378
+ return w === 8
1379
+ ? 0x100 : w === 16
1380
+ ? 0x10000
1381
+ : 0x100000000;
1382
+ }
1383
+ })(this);