      1 /*
      2     Copyright 2008,2009
      3         Matthias Ehmann,
      4         Michael Gerhaeuser,
      5         Carsten Miller,
      6         Bianca Valentin,
      7         Alfred Wassermann,
      8         Peter Wilfahrt
      9
     10     This file is part of JSXGraph.
     11
     12     JSXGraph is free software: you can redistribute it and/or modify
     13     it under the terms of the GNU Lesser General Public License as published by
     14     the Free Software Foundation, either version 3 of the License, or
     15     (at your option) any later version.
     16
     17     JSXGraph is distributed in the hope that it will be useful,
     18     but WITHOUT ANY WARRANTY; without even the implied warranty of
     19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     20     GNU Lesser General Public License for more details.
     21
     22     You should have received a copy of the GNU Lesser General Public License
     23     along with JSXGraph. If not, see <http://www.gnu.org/licenses/>.
     24 */
     25
     26 /**
     27  * @fileoverview The JXG.DataSource is a helper class for data organization. Currently supported data sources are
     28  * javascript arrays and HTML tables.
     29  */
     30
     31 /* NOT YET DOCUMENTED. TODO! */
     32
     33 JXG.DataSource = function() {
     34
     35     this.data = [];
     36     this.columnHeaders = [];
     37     this.rowHeaders = [];
     38
     39     return this;
     40 };
     41
     42 JXG.extend(JXG.DataSource.prototype, /** @lends JXG.DataSource.prototype */ {
     43     loadFromArray: function(table, columnHeader, rowHeader) {
     44         var i, j,cell;
     45
     46         if(typeof columnHeader == 'undefined')
     47             columnHeader = false;
     48         if(typeof rowHeader == 'undefined')
     49             rowHeader = false;
     50
     51         if(JXG.isArray(columnHeader)) {
     52             this.columnHeaders = columnHeader;
     53             columnHeader = false;
     54         }
     55
     56         if(JXG.isArray(rowHeader)) {
     57             this.rowHeaders = rowHeader;
     58             rowHeader = false;
     59         }
     60
     61         this.data = [];
     62         if(columnHeader)
     63             this.columnHeaders = [];
     64         if(rowHeader)
     65             this.rowHeaders = [];
     66
     67         if(typeof table != 'undefined') {
     68             // extract the data
     69             this.data = new Array(table.length);
     70
     71             for(i=0; i<table.length; i++) {
     72                 this.data[i] = new Array(table[i].length);
     73                 for(j=0; j<table[i].length; j++) {
     74                     cell = table[i][j];
     75                     if('' + parseFloat(cell) == cell)
     76                         this.data[i][j] = parseFloat(cell);
     77                     else if (cell != '-')
     78                         this.data[i][j] = cell;
     79                     else
     80                         this.data[i][j] = NaN;
     81                 }
     82             }
     83
     84             if(columnHeader) {
     85                 this.columnHeaders = this.data[0].slice(1);
     86                 this.data = this.data.slice(1);
     87             }
     88
     89             if(rowHeader) {
     90                 this.rowHeaders = new Array();
     91                 for(i=0; i<this.data.length; i++) {
     92                     this.rowHeaders.push(this.data[i][0]);
     93                     this.data[i] = this.data[i].slice(1);
     94                 }
     95             }
     96         }
     97
     98         return this;
     99     },
    100
    101     loadFromTable: function(table, columnHeader, rowHeader) {
    102         var row, i, j, col, cell, name;
    103
    104         if(typeof columnHeader == 'undefined')
    105             columnHeader = false;
    106         if(typeof rowHeader == 'undefined')
    107             rowHeader = false;
    108
    109         if(JXG.isArray(columnHeader)) {
    110             this.columnHeaders = columnHeader;
    111             columnHeader = false;
    112         }
    113
    114         if(JXG.isArray(rowHeader)) {
    115             this.rowHeaders = rowHeader;
    116             rowHeader = false;
    117         }
    118
    119         this.data = [];
    120         if(columnHeader)
    121             this.columnHeaders = [];
    122         if(rowHeader)
    123             this.rowHeaders = [];
    124
    125         // todo: the user should provide the dom node directly
    126         // to adjust: examples in examples folder & wiki
    127         table = document.getElementById(table);
    128
    129         if(typeof table != 'undefined') {
    130             // extract the data
    131             row = table.getElementsByTagName('tr');
    132             this.data = new Array(row.length);
    133
    134             for(i=0; i<row.length; i++) {
    135                 col = row[i].getElementsByTagName('td');
    136                 this.data[i] = new Array(col.length);
    137                 for(j=0; j<col.length; j++) {
    138                     cell = col[j].innerHTML;
    139                     if('' + parseFloat(cell) == cell)
    140                         this.data[i][j] = parseFloat(cell);
    141                     else if (cell != '-')
    142                         this.data[i][j] = cell;
    143                     else
    144                         this.data[i][j] = NaN;
    145                 }
    146             }
    147
    148             if(columnHeader) {
    149                 this.columnHeaders = this.data[0].slice(1);
    150                 this.data = this.data.slice(1);
    151             }
    152
    153             if(rowHeader) {
    154                 this.rowHeaders = new Array();
    155                 for(i=0; i<this.data.length; i++) {
    156                     this.rowHeaders.push(this.data[i][0]);
    157                     this.data[i] = this.data[i].slice(1);
    158                 }
    159             }
    160         }
    161
    162         return this;
    163     },
    164
    165     addColumn: function(name, pos, data) {
    166         // todo
    167     },
    168
    169     addRow: function(name, pos, data) {
    170         // todo
    171     },
    172
    173     getColumn: function(col) {
    174         var result = new Array(this.data.length), i;
    175
    176         // get column index if column is given as column header title
    177         if(typeof col == 'string') {
    178             for(i=0; i<this.columnHeaders.length; i++) {
    179                 if(col == this.columnHeaders[i]) {
    180                     col = i;
    181                     break;
    182                 }
    183             }
    184         }
    185
    186         // build column array
    187         for(i=0; i<this.data.length; i++) {
    188             if(this.data[i].length > col)
    189                 result[i] = parseFloat(this.data[i][col]);
    190         }
    191
    192         return result;
    193     },
    194
    195     getRow: function(row) {
    196         var result, i;
    197
    198         // get column index if column is given as column header title
    199         if(typeof row == 'string') {
    200             for(i=0; i<this.rowHeaders.length; i++) {
    201                 if(row == this.rowHeaders[i]) {
    202                     row = i;
    203                     break;
    204                 }
    205             }
    206         }
    207
    208         // allocate memory for result array
    209         result = new Array(this.data[row].length);
    210
    211         // build column array. result = this.data[row] is a flat copy and will
    212         // destroy our local data copy, that's why we're copying it element wise.
    213         for(i=0; i<this.data[row].length; i++) {
    214             result[i] = this.data[row][i];
    215         }
    216
    217         return result;
    218     }
    219 });
    220