ons_openapi 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,697 @@
1
+ /*
2
+
3
+ JSON-stat Javascript Toolkit v. 0.6.2 - with "window" code commented out
4
+ http://json-stat.org
5
+ https://github.com/badosa/JSON-stat
6
+
7
+ Copyright 2014 Xavier Badosa (http://xavierbadosa.com)
8
+
9
+ Licensed under the Apache License, Version 2.0 (the "License");
10
+ you may not use this file except in compliance with the License.
11
+ You may obtain a copy of the License at
12
+
13
+ http://www.apache.org/licenses/LICENSE-2.0
14
+
15
+ Unless required by applicable law or agreed to in writing, software
16
+ distributed under the License is distributed on an "AS IS" BASIS,
17
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
18
+ or implied. See the License for the specific language governing
19
+ permissions and limitations under the License.
20
+
21
+ */
22
+
23
+ var JSONstat = JSONstat || {};
24
+
25
+ JSONstat.version="0.6.2";
26
+
27
+ function JSONstat(resp,f){
28
+ // if(window===this){
29
+ return new JSONstat.jsonstat(resp,f);
30
+ // }
31
+ }
32
+
33
+ (function(){
34
+ "use strict";
35
+ function isArray(o) {
36
+ return Object.prototype.toString.call(o) === "[object Array]";
37
+ }
38
+
39
+ function jsonstat(o,f){
40
+ var xhr=function(uri, func){
41
+ var json, async=(func!==false);
42
+ // if(window.XDomainRequest && /^(http(s)?:)?\/\//.test(uri)){ //IE9 cross-domain (assuming access to same domain won't be specified using an absolute address). Not integrated because it'll will be removed someday...
43
+ // if(!async){ //JSONstat: IE9 sync cross-domain request? Sorry, not supported (only async if IE9 and cross-domain).
44
+ // return;
45
+ // }
46
+ // var req=new XDomainRequest();
47
+ // /*
48
+ // req.onerror=function(){
49
+ // return; //JSONstat: Can't access "+uri;
50
+ // }
51
+ // */
52
+ // req.onload=function(){
53
+ // json=JSON.parse(req.responseText);
54
+ // func.call(JSONstat(json));
55
+ // }
56
+ // req.open("GET", uri);
57
+ // req.send();
58
+ // } else { //Standard xhr
59
+ var req=new XMLHttpRequest();
60
+ req.onreadystatechange=function(){
61
+ if(req.readyState===4){
62
+ var s=req.status;
63
+ json=(s && req.responseText && (s>=200 && s<300 || s===304)) ? JSON.parse(req.responseText) : null;
64
+ if(async){
65
+ func.call(JSONstat(json));
66
+ }
67
+ }
68
+ }
69
+ req.open("GET",uri,async);
70
+ req.send(null);
71
+ if(!async){
72
+ return json;
73
+ }
74
+ // }
75
+ }
76
+ //sparse cube (value or status)
77
+ //If only one value/status is provided it means same for all (if more than one, then missing values/statuses are nulled).
78
+ function normalize(s,len){
79
+ var ret=[];
80
+
81
+ if(typeof s==="string"){
82
+ s=[s];
83
+ }
84
+ if(isArray(s)){
85
+ if(s.length===len){ //normal case
86
+ return s;
87
+ }
88
+ if(s.length===1){ //all obs same status
89
+ for(var l=0; l<len; l++){
90
+ ret.push(s[0]);
91
+ }
92
+ return ret;
93
+ }
94
+ }
95
+
96
+ //It's an object (sparse cube) or an incomplete array that must be filled with nulls
97
+ for(var l=0; l<len; l++){
98
+ var e=(typeof s[l]==="undefined") ? null: s[l];
99
+ ret.push(e);
100
+ }
101
+ return ret;
102
+ }
103
+
104
+ this.length=0;
105
+ this.id=[];
106
+ if (o===null || typeof o==="undefined"){
107
+ return;
108
+ }
109
+ var type=o.type || "root";
110
+ switch(type){
111
+ case "root" :
112
+ this.type="root";
113
+ var i=[], ds=0;
114
+
115
+ //URI assumed
116
+ if (typeof o==="string" && o.length>0){
117
+ o=xhr(o, typeof f==="function"? f : false);//If second argument is function then async
118
+ }
119
+
120
+ // Wrong input object or wrong URI o connection problem
121
+ if(o===null || typeof o!=="object"){
122
+ return;
123
+ }
124
+
125
+ for (var prop in o){
126
+ ds++;
127
+ /* If sparse cube, we can't rely on value to check size
128
+ if (isArray(o[prop].value)){
129
+ a++;
130
+ }
131
+ */
132
+ i.push(prop);
133
+ }
134
+ this.__tree__=o;
135
+ this.length=ds;
136
+ this.id=i;
137
+ break;
138
+ case "ds" :
139
+ this.type="ds";
140
+ if (!o.hasOwnProperty("__tree__")){
141
+ return;
142
+ }
143
+ var ot=o.__tree__;
144
+ this.__tree__=ot;
145
+ this.label=ot.label || null;
146
+ this.updated=ot.updated || null;
147
+ this.source=ot.source || null; //v.0.5.0
148
+
149
+ //Sparse cube (If toTable() removed, this logic can be moved inside Data()
150
+ //which is more efficient when retrieving a single value/status.
151
+ var dsize=0; //data size
152
+ if (ot.hasOwnProperty("value") && isArray(ot.value)){
153
+ dsize=ot.value.length;
154
+ }else{
155
+ if (ot.hasOwnProperty("status") && isArray(ot.status)){
156
+ dsize=ot.status.length;
157
+ }else{
158
+ if(ot.hasOwnProperty("dimension")) {
159
+ var size=this.__tree__.dimension.size, length=1;
160
+ for(var s=size.length; s--;){
161
+ length*=size[s];
162
+ }
163
+ dsize=length;
164
+ }
165
+ }
166
+ }
167
+
168
+ this.value=normalize(ot.value,dsize);
169
+ this.status=(!(ot.hasOwnProperty("status"))) ? null : normalize(ot.status,dsize);
170
+
171
+ // if dimensions are defined, id and size arrays are required and must have equal length
172
+ if (ot.hasOwnProperty("dimension")){
173
+ if (
174
+ !(isArray(ot.dimension.id)) ||
175
+ !(isArray(ot.dimension.size)) ||
176
+ ot.dimension.id.length!=ot.dimension.size.length
177
+ ){
178
+ return;
179
+ }
180
+ var otd=ot.dimension;
181
+ this.length=otd.size.length;
182
+ this.id=otd.id;
183
+ this.role=otd.role; //0.3.5 Role added
184
+ this.n=dsize; //number of obs added in 0.4.2
185
+
186
+ //If only one category, no need of index according to the spec
187
+ //This actually will recreate an index even if there are more than one category and no index is provided
188
+ //but because there's no guarantee that properties are retrieved in a particular order (even though it worked in Ch,FF,IE,Sa,Op)
189
+ //(Main problem in fact is that you don't have to WRITE them in a particular order) the original order of categories could
190
+ //theoretically be changed. That's why the procedure will only be valid when there's only one category.
191
+ //Note: If toTable() is removed it would make more sense to move this loop inside Dimension() as it is not needed for Data().
192
+ for(var d=0, len=this.length; d<len; d++){
193
+ if (!(otd[otd.id[d]].category.hasOwnProperty("index"))){
194
+ var c=0;
195
+ otd[otd.id[d]].category.index={};
196
+ for (var prop in otd[otd.id[d]].category.label){
197
+ otd[otd.id[d]].category.index[prop]=c++;
198
+ }
199
+ }else{
200
+ // If index is array instead of object convert into object
201
+ // That is: we normalize it (instead of defining a function depending on
202
+ // index type to read categories -maybe in the future when indexOf can be
203
+ // assumed for all browsers and default is array instead of object-)
204
+ if(isArray(otd[otd.id[d]].category.index)){
205
+ var oindex={}, index=otd[otd.id[d]].category.index;
206
+ for (var i=0, ilen=index.length; i<ilen; i++){
207
+ oindex[index[i]]=i;
208
+ }
209
+ otd[otd.id[d]].category.index=oindex;
210
+ }
211
+ }
212
+ }
213
+ }else{
214
+ this.length=0;
215
+ }
216
+ break;
217
+ case "dim" :
218
+ this.type="dim";
219
+ var cats=[], ot=o.__tree__, otc=ot.category;
220
+ if (
221
+ !o.hasOwnProperty("__tree__") ||
222
+ !ot.hasOwnProperty("category") //Already tested in the Dimension() / Category() ? method
223
+ ){
224
+ return;
225
+ }
226
+
227
+ //If no category label, use IDs
228
+ if(!otc.hasOwnProperty("label")){
229
+ otc.label={};
230
+ for (var prop in otc.index){
231
+ otc.label[prop]=prop;
232
+ }
233
+ }
234
+
235
+ //Array conversion
236
+ for (var prop in otc.index){
237
+ cats[otc.index[prop]]=prop; //0.4.3 cats.push(prop) won't do because order not in control when index was originally an array and was converted to object by the Toolkit.
238
+ }
239
+
240
+ this.__tree__=ot;
241
+ //When no dimension label, undefined is returned.
242
+ //Discarded options: null / dim
243
+ this.label=ot.label || null;
244
+ this.id=cats;
245
+ this.length=cats.length;
246
+ this.role=o.role;
247
+ this.hierarchy=otc.hasOwnProperty("child"); //0.6.0
248
+ break;
249
+ case "cat" :
250
+ var par=o.child;
251
+ this.type="cat";
252
+
253
+ //0.5.0 changed. It was autoreference: id. And length was 0 always
254
+ this.id=par;
255
+ this.length=(par===null) ? 0 : par.length;
256
+
257
+ this.index=o.index;
258
+ this.label=o.label;
259
+ this.unit=o.unit; //v.0.5.0
260
+ this.coordinates=o.coord; //v.0.5.0
261
+ break;
262
+ }
263
+ }
264
+
265
+ jsonstat.prototype.Dataset=function(ds){
266
+ if (this===null || this.type!=="root"){
267
+ return null;
268
+ }
269
+ if(typeof ds==="undefined"){
270
+ var ar=[];
271
+ for(var c=0, len=this.id.length; c<len; c++){
272
+ ar.push(this.Dataset(this.id[c]));
273
+ }
274
+ return ar;
275
+ }
276
+ if(typeof ds==="number"){
277
+ var num=this.id[ds];
278
+ return (typeof num!=="undefined") ? this.Dataset(num) : null;
279
+ }
280
+
281
+ var tds=this.__tree__[ds];
282
+ if(typeof tds==="undefined"){
283
+ return null;
284
+ }
285
+
286
+ return new jsonstat({"type" : "ds", "__tree__": tds});
287
+ }
288
+
289
+ jsonstat.prototype.Dimension=function(dim){
290
+ function role(otd,dim){
291
+ var otdr=otd.role;
292
+ if(typeof otdr!="undefined"){
293
+ for(var prop in otdr){
294
+ for(var p=otdr[prop].length;p--;){
295
+ if(otdr[prop][p]===dim){
296
+ return prop;
297
+ }
298
+ }
299
+ }
300
+ }
301
+ return null;
302
+ }
303
+
304
+ if (this===null || this.type!=="ds"){
305
+ return null;
306
+ }
307
+ if(typeof dim==="undefined"){
308
+ var ar=[];
309
+ for(var c=0, len=this.id.length; c<len; c++){
310
+ ar.push(this.Dimension(this.id[c]));
311
+ }
312
+ return ar;
313
+ }
314
+ if(typeof dim==="number"){
315
+ var num=this.id[dim];
316
+ return (typeof num!=="undefined") ? this.Dimension(num) : null;
317
+ }
318
+
319
+ var otd=this.__tree__.dimension;
320
+ if(typeof otd==="undefined"){
321
+ return null;
322
+ }
323
+
324
+ //currently only "role" is supported as filter criterion
325
+ if(typeof dim==="object"){
326
+ if(dim.hasOwnProperty("role")){
327
+ var ar=[];
328
+ for(var c=0, len=this.id.length; c<len; c++){
329
+ var oid=this.id[c];
330
+ if(role(otd,oid)===dim.role){
331
+ ar.push(this.Dimension(oid));
332
+ }
333
+ }
334
+ return (typeof ar[0]==="undefined") ? null : ar;
335
+ }else{
336
+ return null;
337
+ }
338
+ }
339
+
340
+ var otdd=otd[dim];
341
+ if(typeof otdd==="undefined"){
342
+ return null;
343
+ }
344
+
345
+ return new jsonstat({"type" : "dim", "__tree__": otdd, "role": role(otd,dim)});
346
+ }
347
+
348
+ jsonstat.prototype.Category=function(cat){
349
+ if (this===null || this.type!=="dim"){
350
+ return null;
351
+ }
352
+ if(typeof cat==="undefined"){
353
+ var ar=[];
354
+ for(var c=0, len=this.id.length; c<len; c++){
355
+ ar.push(this.Category(this.id[c]));
356
+ }
357
+ return ar;
358
+ }
359
+ if(typeof cat==="number"){
360
+ var num=this.id[cat];
361
+ return (typeof num!=="undefined") ? this.Category(num) : null;
362
+ }
363
+
364
+ var oc=this.__tree__.category;
365
+ if(typeof oc==="undefined"){
366
+ return null;
367
+ }
368
+ var index=oc.index[cat];
369
+ if(typeof index==="undefined"){
370
+ return null;
371
+ }
372
+
373
+ var unit=(oc["unit"] && oc["unit"][cat]) || null;
374
+ var coord=(oc["coordinates"] && oc["coordinates"][cat]) || null;
375
+ var child=(oc["child"] && oc["child"][cat]) || null;
376
+ return new jsonstat({"type" : "cat", "index": index, "label": oc.label[cat], "child" : child, "unit" : unit, "coord" : coord});
377
+ }
378
+
379
+ jsonstat.prototype.Data=function(e){
380
+ function firstprop(o){
381
+ for (var p in o) {
382
+ if(o.hasOwnProperty(p)){
383
+ return p;
384
+ }
385
+ }
386
+ }
387
+ function dimObj2Array(thisds, obj){
388
+ var a=[], dim=thisds.dimension, di=dim.id;
389
+ for (var d=0, len=di.length; d<len; d++){
390
+ var id=di[d], cat=obj[id];
391
+ //If dimension not defined and dim size=1, take first category (user not forced to specify single cat dimensions)
392
+ a.push(typeof cat==="string" ? cat : dim.size[d]===1 ? firstprop(dim[id].category.index) : null);
393
+ }
394
+ return a;
395
+ }
396
+
397
+ if(this===null || this.type!=="ds"){
398
+ return null;
399
+ }
400
+
401
+ if(typeof e==="undefined"){
402
+ //Before 0.4.2
403
+ //return {"value" : this.value, "status": this.status, "label": tree.label, "length" : this.value.length};
404
+ //Since 0.4.2: normalized as array of objects
405
+ for(var i=0, ret=[], len=this.value.length; i<len; i++){
406
+ ret.push(this.Data(i));
407
+ }
408
+ return ret;
409
+ }
410
+
411
+ //Data By Position in original array
412
+ if(typeof e==="number"){
413
+ var num=this.value[e];
414
+ return (typeof num!=="undefined") ?
415
+ {"value" : num, "status":
416
+ (this.status) ?
417
+ this.status[e]
418
+ :
419
+ null
420
+ }
421
+ :
422
+ null
423
+ ; /* removed in 0.5.2.2 length: 1 {"value" : undefined, "status": undefined, "length" : 0};*/
424
+ }
425
+
426
+ var tree=this.__tree__, n=tree.dimension.size, dims=n.length //same as this.length;
427
+
428
+ //DataByPosition in every dim
429
+ //If more positions than needed are provided, they will be ignored.
430
+ //Less positions than needed will return undefined
431
+ if(isArray(e)){
432
+ if(this.length!==e.length){ //0.5.2.2
433
+ return null;
434
+ }
435
+ var mult=1,
436
+ res=0,
437
+ miss=[],
438
+ nmiss=[],
439
+ ret=[]
440
+ ;
441
+ //Validate dim index
442
+ //And loop to find missing dimensions
443
+ for(var i=0; i<dims; i++){
444
+ if(typeof e[i]!=="undefined"){
445
+ if(typeof e[i]!=="number" || e[i]>=n[i]){
446
+ return null; /* removed in 0.5.2.2 {"value" : undefined, "status": undefined, "length" : 0};*/
447
+ }
448
+ //Used if normal case (miss.length===0)
449
+ mult*=(i>0) ? n[(dims-i)] : 1;
450
+ res+=mult*e[dims-i-1]; //simplified in 0.4.3
451
+ }else{
452
+ //Used if missing dimensions miss.length>0
453
+ miss.push(i); //missing dims
454
+ nmiss.push(n[i]); //missing dims size
455
+ }
456
+ }
457
+
458
+ //If all dims are specified, go ahead as usual.
459
+ //If one non-single dimension is missing create array of results
460
+ //If more than one non-single dimension is missing, WARNING
461
+ if(miss.length>1){
462
+ return null; /* removed in 0.5.2.2 {"value" : undefined, "status": undefined, "length" : 0};*/
463
+ }
464
+ if(miss.length===1){
465
+ for(var c=0, clen=nmiss[0]; c<clen; c++){
466
+ var na=[]; //new array
467
+ for(var i=0; i<dims; i++){
468
+ if(i!==miss[0]){
469
+ na.push(e[i]);
470
+ }else{
471
+ na.push(c);
472
+ }
473
+ }
474
+ ret.push(this.Data(na));
475
+ }
476
+ return ret;
477
+ }
478
+
479
+ //miss.length===0 (use previously computed res) //simplified in 0.4.3
480
+ return {"value" : this.value[res], "status": (this.status) ? this.status[res] : null/*, "length" : 1*/};
481
+ }
482
+
483
+ var id=dimObj2Array(tree, e);
484
+ var pos=[], otd=tree.dimension;
485
+ for(var i=0, len=id.length; i<len; i++){
486
+ pos.push(otd[otd.id[i]].category.index[id[i]]);
487
+ }
488
+ //Dimension cat undefined means a loop (by position) is necessary
489
+ return this.Data(pos);
490
+ }
491
+
492
+ /*
493
+ Transformation method: output in DataTable format (array or object)
494
+ Setup: opts={status: false, slabel: "Status", vlabel: "Value", field: "label", content: "label", type: "array"} (type values: "array" / "object" / "arrobj")
495
+
496
+ PENDING: use metric or any dim cat IDs instead of "value" and assign as many fields as metrics (pivot "by").
497
+ */
498
+ jsonstat.prototype.toTable=function(opts, func){
499
+ if(this===null || this.type!=="ds"){
500
+ return null;
501
+ }
502
+
503
+ if(arguments.length==1 && typeof opts==="function"){
504
+ func=opts, opts=null;
505
+ }
506
+ var
507
+ dataset=this.__tree__,
508
+ opts=opts || {field: "label", content: "label", vlabel: "Value", slabel: "Status", type: "array", status: false} //default: use label for field names and content instead of "id"
509
+ ;
510
+
511
+ if(typeof func==="function"){
512
+ var
513
+ totbl=this.toTable(opts),
514
+ ret=[],
515
+ i=(opts.type!=='array') ? 0 : 1 //first row is header in array and object
516
+ ;
517
+
518
+ if(opts.type!=='object'){
519
+ var arr=totbl.slice(i);
520
+ }else{
521
+ var arr=totbl.rows.slice(0);
522
+ }
523
+
524
+ for(var r=0, len=arr.length; r<len; r++){
525
+ var a=func.call(
526
+ this, //0.5.3
527
+ arr[r], //Discarded for efficiency: (opts.type!=='object') ? arr[r] : arr[r].c,
528
+ r
529
+ );
530
+ if (typeof a!=="undefined"){
531
+ ret.push(a);
532
+ }
533
+ }
534
+ if (opts.type==='object'){
535
+ return {cols: totbl.cols, rows: ret};
536
+ }
537
+ if(opts.type==='array'){
538
+ ret.unshift(totbl[0]);
539
+ }
540
+ return ret;
541
+ }
542
+
543
+ //For example, as D3 input
544
+ if(opts.type==="arrobj"){
545
+ var
546
+ totbl=this.toTable({field: "id", content: opts.content, status: opts.status}),// At the moment, options besides "type" are not passed
547
+ tbl=[],
548
+ head=totbl.shift()
549
+ ;
550
+
551
+ for(var i=0, len=totbl.length; i<len; i++){ //Can't be done with i-- as we want to keep the original order
552
+ var tblr={};
553
+ for(var j=totbl[i].length;j--;){
554
+ tblr[head[j]]=totbl[i][j];
555
+ }
556
+ tbl.push(tblr);
557
+ }
558
+ return tbl;
559
+ }
560
+
561
+ var useid=(opts.field==="id");
562
+
563
+ if(opts.type==="object"){
564
+ //Object
565
+ var
566
+ valuetype=(typeof this.value[0]==="number" || this.value[0]===null) ? "number" : "string", //cell type inferred from first cell. If null, number is assumed (naif)
567
+ addCol=function(dimid,dimlabel){
568
+ var label=(useid && dimid) || dimlabel || dimid; //if userid then id; else label; then id if not label
569
+ cols.push({id: dimid, label: label, type: "string"}); //currently not using datetime Google type (requires a Date object)
570
+ },
571
+ addColValue=function(str1,str2,status){
572
+ var
573
+ vlabel=(useid && "value") || str1|| "Value",
574
+ slabel=(useid && "status") || str2|| "Status"
575
+ ;
576
+ if(status){
577
+ cols.push({id: "status", label: slabel, type: "string"});
578
+ }
579
+ cols.push({id: "value", label: vlabel, type: valuetype});
580
+ },
581
+ addRow=function(r){
582
+ row.push({v: r});
583
+ },
584
+ addRowValue=function(r){
585
+ //At the moment, no support for formatted values (f: formatted)
586
+ row.push({v: r});
587
+ rows.push({c: row});
588
+ }
589
+ ;
590
+ }else{
591
+ //Array
592
+ var
593
+ addCol=function(dimid,dimlabel){
594
+ var colid=(useid && dimid) || dimlabel || dimid; //if userid then id; else label; then id if not label
595
+ cols.push(colid);
596
+ },
597
+ addColValue=function(str1,str2,status){
598
+ var
599
+ vlabel=(useid && "value") || str1 || "Value",
600
+ slabel=(useid && "status") || str2 || "Status"
601
+ ;
602
+ if(status){
603
+ cols.push(slabel);
604
+ }
605
+ cols.push(vlabel);
606
+ table.push(cols);
607
+ },
608
+ addRow=function(r){
609
+ row.push(r);
610
+ },
611
+ addRowValue=function(r){
612
+ row.push(r);
613
+ table.push(row);
614
+ }
615
+ ;
616
+ }
617
+
618
+ var dd=dataset.dimension, ddi=dd.id, ddil=ddi.length, dds=dd.size;
619
+ if (ddil!=dds.length){
620
+ return false;
621
+ }
622
+ var dim=[], total=1, m=1, mult=[], dimexp=[], label=[], table=[], cols=[], rows=[];
623
+ for (var i=0; i<ddil; i++){
624
+ var dimid=ddi[i],
625
+ dimlabel=dd[dimid].label
626
+ ;
627
+ addCol(dimid,dimlabel); //Global cols
628
+
629
+ total*=dds[i];
630
+ m*=dds[i];
631
+ var cat=[];
632
+ for (var j=0; j<dds[i]; j++){
633
+ for (var catid in dd[ddi[i]].category.index){
634
+ if (dd[ddi[i]].category.index[catid]===j){
635
+ var rowid=(opts.content!=="id" && dd[ddi[i]].category.label) ? dd[ddi[i]].category.label[catid] : catid; //id if not label (Maybe move label normalization from "dim" to "ds"?)
636
+ cat.push(rowid);
637
+ }
638
+ }
639
+ }
640
+ dim.push(cat);
641
+ mult.push(m);
642
+ }
643
+ addColValue(opts.vlabel,opts.slabel,opts.status); //Global cols and table
644
+
645
+ //end of inversion: now use dim array
646
+ for (var d=0, len=dim.length; d<len; d++){
647
+ var catexp=[];
648
+ for (var c=0, len2=dim[d].length; c<len2; c++){
649
+ //get the label repetitions
650
+ for (var n=0; n<total/mult[d]; n++){
651
+ catexp.push(dim[d][c]);
652
+ }
653
+ }
654
+ dimexp.push(catexp);
655
+ }
656
+ for (var d=0, len=dimexp.length; d<len; d++){
657
+ var l=[], e=0;
658
+ for (var x=0; x<total; x++){
659
+ l.push(dimexp[d][e]);
660
+ e++;
661
+ if (e===dimexp[d].length){
662
+ e=0;
663
+ }
664
+ }
665
+ label.push(l);
666
+ }
667
+ for (var x=0; x<total; x++){
668
+ var row=[];
669
+ for (var d=0, len=dimexp.length; d<len; d++){
670
+ addRow(label[d][x]); //Global row
671
+ }
672
+ if(opts.status){
673
+ addRow(this.status[x]);
674
+ }
675
+ addRowValue(this.value[x]); //Global row, rows and table
676
+ }
677
+
678
+ if(opts.type==="object"){
679
+ return {cols: cols, rows: rows};
680
+ }else{
681
+ return table;
682
+ }
683
+ }
684
+
685
+ jsonstat.prototype.node=function(){
686
+ return this.__tree__;
687
+ }
688
+
689
+ jsonstat.prototype.toString=function(){
690
+ return this.type; //improve?
691
+ }
692
+ jsonstat.prototype.toValue=function(){
693
+ return this.length;
694
+ }
695
+
696
+ JSONstat.jsonstat=jsonstat;
697
+ })();