ons_openapi 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ })();