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