1 /* 2 Copyright 2008-2024 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 dual licensed under the GNU LGPL or MIT License. 13 14 You can redistribute it and/or modify it under the terms of the 15 16 * GNU Lesser General Public License as published by 17 the Free Software Foundation, either version 3 of the License, or 18 (at your option) any later version 19 OR 20 * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT 21 22 JSXGraph is distributed in the hope that it will be useful, 23 but WITHOUT ANY WARRANTY; without even the implied warranty of 24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 GNU Lesser General Public License for more details. 26 27 You should have received a copy of the GNU Lesser General Public License and 28 the MIT License along with JSXGraph. If not, see <https://www.gnu.org/licenses/> 29 and <https://opensource.org/licenses/MIT/>. 30 */ 31 32 /*global JXG: true, define: true, document: true*/ 33 /*jslint nomen: true, plusplus: true*/ 34 35 /** 36 * @fileoverview The JXG.DataSource is a helper class for data organization. Currently supported data sources are 37 * javascript arrays and HTML tables. 38 */ 39 40 import JXG from "../jxg.js"; 41 import Type from "../utils/type.js"; 42 43 JXG.DataSource = function () { 44 this.data = []; 45 this.columnHeaders = []; 46 this.rowHeaders = []; 47 48 return this; 49 }; 50 51 JXG.extend( 52 JXG.DataSource.prototype, 53 /** @lends JXG.DataSource.prototype */ { 54 loadFromArray: function (table, columnHeader, rowHeader) { 55 var i, j, cell; 56 57 if (Type.isArray(columnHeader)) { 58 this.columnHeaders = columnHeader; 59 columnHeader = false; 60 } 61 62 if (Type.isArray(rowHeader)) { 63 this.rowHeaders = rowHeader; 64 rowHeader = false; 65 } 66 67 this.data = []; 68 69 if (columnHeader) { 70 this.columnHeaders = []; 71 } 72 73 if (rowHeader) { 74 this.rowHeaders = []; 75 } 76 77 if (Type.exists(table)) { 78 // extract the data 79 this.data = []; 80 81 for (i = 0; i < table.length; i++) { 82 this.data[i] = []; 83 84 for (j = 0; j < table[i].length; j++) { 85 cell = table[i][j]; 86 if (parseFloat(cell).toString() === cell) { 87 this.data[i][j] = parseFloat(cell); 88 } else if (cell !== "-") { 89 this.data[i][j] = cell; 90 } else { 91 this.data[i][j] = NaN; 92 } 93 } 94 } 95 96 if (columnHeader) { 97 this.columnHeaders = this.data[0].slice(1); 98 this.data = this.data.slice(1); 99 } 100 101 if (rowHeader) { 102 this.rowHeaders = []; 103 for (i = 0; i < this.data.length; i++) { 104 this.rowHeaders.push(this.data[i][0]); 105 this.data[i] = this.data[i].slice(1); 106 } 107 } 108 } 109 110 return this; 111 }, 112 113 loadFromTable: function (table, columnHeader, rowHeader) { 114 var row, i, j, col, cell; 115 116 if (Type.isArray(columnHeader)) { 117 this.columnHeaders = columnHeader; 118 columnHeader = false; 119 } 120 121 if (Type.isArray(rowHeader)) { 122 this.rowHeaders = rowHeader; 123 rowHeader = false; 124 } 125 126 this.data = []; 127 128 if (columnHeader) { 129 this.columnHeaders = []; 130 } 131 132 if (rowHeader) { 133 this.rowHeaders = []; 134 } 135 136 // to adjust: examples in examples folder & wiki 137 table = document.getElementById(table); 138 139 if (Type.exists(table)) { 140 // extract the data 141 row = table.getElementsByTagName("tr"); 142 this.data = []; 143 144 for (i = 0; i < row.length; i++) { 145 col = row[i].getElementsByTagName("td"); 146 this.data[i] = []; 147 148 for (j = 0; j < col.length; j++) { 149 cell = col[j].innerHTML; 150 151 if (parseFloat(cell).toString() === cell) { 152 this.data[i][j] = parseFloat(cell); 153 } else if (cell !== "-") { 154 this.data[i][j] = cell; 155 } else { 156 this.data[i][j] = NaN; 157 } 158 } 159 } 160 161 if (columnHeader) { 162 this.columnHeaders = this.data[0].slice(1); 163 this.data = this.data.slice(1); 164 } 165 166 if (rowHeader) { 167 this.rowHeaders = []; 168 for (i = 0; i < this.data.length; i++) { 169 this.rowHeaders.push(this.data[i][0]); 170 this.data[i] = this.data[i].slice(1); 171 } 172 } 173 } 174 175 return this; 176 }, 177 178 addColumn: function (name, pos, data) { 179 throw new Error("not implemented"); 180 }, 181 182 addRow: function (name, pos, data) { 183 throw new Error("not implemented"); 184 }, 185 186 getColumn: function (col) { 187 var i, 188 result = []; 189 190 // get column index if column is given as column header title 191 if (Type.isString(col)) { 192 for (i = 0; i < this.columnHeaders.length; i++) { 193 if (col === this.columnHeaders[i]) { 194 col = i; 195 break; 196 } 197 } 198 } 199 200 // build column array 201 for (i = 0; i < this.data.length; i++) { 202 if (this.data[i].length > col) { 203 result[i] = parseFloat(this.data[i][col]); 204 } 205 } 206 207 return result; 208 }, 209 210 getRow: function (row) { 211 var result, i; 212 213 // get column index if column is given as column header title 214 if (Type.isString(row)) { 215 for (i = 0; i < this.rowHeaders.length; i++) { 216 if (row === this.rowHeaders[i]) { 217 row = i; 218 break; 219 } 220 } 221 } 222 223 // allocate memory for result array 224 result = []; 225 226 // build column array. result = this.data[row] is a flat copy and will 227 // destroy our local data copy, that's why we're copying it element wise. 228 for (i = 0; i < this.data[row].length; i++) { 229 result[i] = this.data[row][i]; 230 } 231 232 return result; 233 } 234 } 235 ); 236 237 export default JXG.DataSource; 238