I'm trying to create a graph from values I get from the https://financialmodelingprep.com/ API. Basically what I did so far is that I create a table with all the values like this:
function myFunction() {
var symbol =
document.getElementById("Ticker").value;
//var symbol = "TSLA";
// https://financialmodelingprep.com/developer/docs
getRequest(
'https://financialmodelingprep.com/api/v3/financials/income-statement/' + symbol + '?period=quarter',
drawOutput
);
function drawOutput(responseText) {
let resp = JSON.parse(responseText).financials;
let financials = resp;
let $table = document.createElement("table");
$table.className += " table2";
var elements = document.querySelectorAll('.stock-name')[0];
let $head = document.createElement("thead");
let $body = document.createElement("tbody");
let $lineHader = document.createElement("tr");
/* let $elefirst = document.createElement("th");
$elefirst.textContent = 'Fiscal';
$lineHader.appendChild($elefirst); */
for (let i = 0; i < financials.length; i++) {
let financial = financials[i];
let $line = document.createElement("tr");
for (var key in financial) {
if (i === 0 && financial.hasOwnProperty(key)) {
let $ele = document.createElement("th");
$ele.textContent = key;
$lineHader.appendChild($ele);
}
}
$head.appendChild($lineHader);
$table.appendChild($head);
var z = 0;
for (var key2 in financial) {
if (financial.hasOwnProperty(key2)) {
/* if (z === 0) {
let title = Object.keys(resp)[i];
let $eleTile = document.createElement("td");
$eleTile.textContent = title;
$line.appendChild($eleTile);
} */
let $eletd = document.createElement("td");
if (z === 0) {
$eletd.textContent = financial[key2];
} else {
$eletd.textContent = financial[key2];
}
$line.appendChild($eletd);
}
z++;
}
$body.appendChild($line)
$table.appendChild($body);
}
document.body.appendChild($table);
}
function getRequest(url, success) {
var req = false;
try {
req = new XMLHttpRequest();
} catch (e) {
try {
req = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
req = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
return false;
}
}
}
if (!req) return false;
if (typeof success != 'function') success = function() {};
req.onreadystatechange = function() {
if (req.readyState == 4) {
if (req.status === 200) {
success(req.responseText)
}
}
}
req.open("GET", url, true);
req.send(null);
return req;
}
}
</script>
<div class="stock-name"></div>
Which will look something like This
What I'm trying to do is to get the 2nd Column so the Revenue and graph those values with this:
<canvas id="myChart" width="400" height="200"></canvas>
<script>
var ctx = document.getElementById('myChart');
var myLineChart = new Chart(ctx, {
type: 'line',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [2, 1, 3, 5, 2, 3],
backgroundColor: 'rgba(255, 99, 132, 0.2)',
borderColor: 'rgba(255, 99, 132, 1)',
borderWidth: 1,
fill: false,
showLine: true,
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
And basically plug in the Revenue to the data values which are currently 2, 1, 3, 5, 2, 3 . I would appreciate any help possible.
I can help you fetch the second row but not graphing it.
For this to work, your table needs to be in the html, and you need to add an id to the table like so:
$table.id = "chartTable";
Put this after the let $table = createElement() or whatever.
Then:
let secondRow = document.querySelectorAll('#' + $table.id + ' tr')[1].;
Edit:
For columns:
let rows = document.querySelectorAll('#' + $table.id + ' tr'), i, col = [];
for (i = 0; i < rows.length; i++) {
let row = rows[i][1];
col.push(row.innerText);
}
Then the col array would contain all the values.
Explanation (for the columns bit):
To access the second column, you need to access the second value of each row.
Second Edit:
let tds = document.querySelectorAll('#' + $table.id + ' tr td'), i, col = [];
let l = 20; // l is the number of elements in a **row**
for (i = 1; i < tds.length; i += l) {
col.push(tds[i].innerHTML);
}
Related
blue is the standard, the red is current mine
compared with these two diagrams, I do not no how to design the x-axis in the blue diagram, which is a range to describe the data.
Now, I using an array to store all value displayed, and on the y-axis, another array stores the times of each number displays. But I do not know make the X-axis to be a range.
<script>
var sheetName = null;
var sheets = null;
var ageArray = new Array();
var ageTimes = new Array();
function readExcel(file_obj){
var reader = new FileReader();
var file = file_obj.files[0];
reader.readAsBinaryString(file);
reader.onload = function (e) {
var data = e.target.result;
var wb = XLSX.read(data, {type: 'binary'});
sheetName = wb.SheetNames[0] // 获取文档中第一个sheet页签的名字
sheets = wb.Sheets[sheetName] // 获sheet名页签下的数据
var json = XLSX.utils.sheet_to_json(sheets)
// console.log(sheets); // 返回sheet对象到控制台
// console.log(json.length);
// console.log(json);
for (let i = 0; i < json.length; i++) {
ageArray.push(json[i]['Age ']);
}
// console.log(ageArray);
function unique (arr) {
return Array.from(new Set(arr))
}
ageArray = unique(ageArray);
ageArray.sort(function (a,b){
if (a>b) {
return 1
} else if (a<b){
return -1
} else return 0
});
// console.log(ageArray);
// count times
let LevelList = json.map(item => {
return item['Age '];
})
let contlist = LevelList.reduce(function(prev,next){
prev[next] = (prev[next]+1) || 1;
return prev
},{});
console.log(contlist);
for (let j = 0; j < ageArray.length; j++) {
var index = ageArray[j];
// console.log(contlist[index]);//
ageTimes.push(contlist[index]);
// console.log(ageTimes);
}
var myChart = echarts.init(document.querySelector('.box'));
var option = {
title: {
text: 'ECharts'
},
tooltip: {},
legend: {
data: ['sale']
},
xAxis: {
data: ageArray,
},
yAxis: {
},
series: [
{
name: 'sale',
type: 'bar',
data: ageTimes
}
]
};
myChart.setOption(option);
};
}
</script>
<style>
.box {
width: 1000px;
height: 400px;
background-color: pink;
}
</style>
<body>
<input type="file" onchange="readExcel(this)" />
<div class="box"></div>
</body>
I am retrieving a JSON data using XMLHttp request and I have them in a table. I want to introduce pagination such that each page will only display 5 sets of data using only the very basics of javascript. I tried using an unordered list and then onclick, I tried using buttons, but I am not getting the desired result. I am really new to this and I am out of ideas. Kindly provide some insight on how to achieve the desired output.
var request = new XMLHttpRequest();
request.open('GET', 'https://raw.githubusercontent.com/Rajavasanthan/jsondata/master/pagenation.json', true);
request.send();
request.onload = function() {
var data = JSON.parse(request.response);
console.log(data);
var table = document.createElement('table');
table.setAttribute('class', 'table');
var thead = document.createElement('thead');
thead.setAttribute('class', 'thead-dark')
var tr = document.createElement('tr');
var tbody = document.createElement('tbody');
var th1 = document.createElement('th')
th1.innerHTML = 'id'
var th2 = document.createElement('th');
th2.innerHTML = 'Name'
var th3 = document.createElement('th');
th3.innerHTML = 'Email';
tr.append(th1, th2, th3);
thead.append(tr);
table.append(thead);
var i = 0;
for (let num = 1; num <= 20; num++) {
for (let x = i * 5; x < ((i + 1) * 5); x++) {
let k = data[x];
foo(k.id, k.name, k.email, x);
}
i++
}
function foo(id, name, email, rownum) {
var td1 = document.createElement('td');
var td2 = document.createElement('td');
var td3 = document.createElement('td');
td1.innerHTML = id
td2.innerHTML = name;
td3.innerHTML = email;
var tr = document.createElement('tr');
if (rownum % 2 === 0) tr.setAttribute('style', 'background-color:#d3d3d3');
tr.append(td1, td2, td3);
tbody.append(tr);
table.append(tbody);
}
document.body.append(table);
}
From your OP, I 'm not exactly sure what issue you are running into. You'll need to track your table results in order for a user to navigate forward and backwards. How you track your results is up to you, but I created a snippet below showcasing an example. I assume your data is structured as an array of objects. This example should get you started.
Basically, the code keeps track of which records are displayed by saving their index within the data attribute of the table. Then, when a user sends a command to navigate the page, the code will use these index numbers to retrieve the next or previous set of records for displaying on the table.
const table = document.querySelector('table');
const theadRow = table.querySelector('thead tr')
const tbody = table.querySelector('tbody')
const navigation = document.querySelector('.navigation');
const myDataArray = [{
id: '001',
name: "bob",
email: 'nothing#aol.com'
},
{
id: '002',
name: "susy",
email: 'nothing#aol.com'
},
{
id: '003',
name: "jim",
email: 'nothing#aol.com'
},
{
id: '004',
name: "anny",
email: 'nothing#aol.com'
},
{
id: '005',
name: "greg",
email: 'nothing#aol.com'
},
{
id: '006',
name: "pepe",
email: 'nothing#aol.com'
},
{
id: '007',
name: "mickey",
email: 'nothing#aol.com'
},
]
const paginationConfig = {
resultsPerPage: 2,
}
// set default page start
table.dataset.recordStart = 0
table.dataset.recordEnd = paginationConfig.resultsPerPage - 1
displayDefaultTablePage(myDataArray)
function displayDefaultTablePage(data) {
let currentRecordStart = parseInt(table.dataset.recordStart)
let currentRecordEnd = parseInt(table.dataset.recordEnd)
let headerLabels = Object.keys(data[0])
for (let i = 0; i < headerLabels.length; i++) {
let th = document.createElement('th')
th.textContent = headerLabels[i]
theadRow.append(th)
}
let recordsToDisplay = data.slice(currentRecordStart, currentRecordEnd + 1)
createTbodyCells(recordsToDisplay)
}
// listen for user commands
navigation.addEventListener('click', (e) => {
if (e.target.matches('.next')) {
changePage('next')
} else {
changePage('prev')
}
})
// determine direction and initialize the page change
function changePage(direction) {
let currentRecordStart = parseInt(table.dataset.recordStart)
let currentRecordEnd = parseInt(table.dataset.recordEnd)
if (direction === 'next') {
if(currentRecordEnd+1>myDataArray.length){
return
}
let newStart = currentRecordEnd + 1
let newEnd = newStart + paginationConfig.resultsPerPage - 1
table.dataset.recordStart = newStart
table.dataset.recordEnd = newEnd
let recordsToDisplay = myDataArray.slice(newStart, newEnd + 1)
createTbodyCells(recordsToDisplay)
} else if (direction === 'prev') {
if(currentRecordStart==0){
return
}
let newEnd = currentRecordStart - 1
let newStart = newEnd - paginationConfig.resultsPerPage+1
table.dataset.recordStart = newStart
table.dataset.recordEnd = newEnd
let recordsToDisplay = myDataArray.slice(newStart, newEnd + 1)
createTbodyCells(recordsToDisplay)
} else {
return
}
}
// add records to DOM
function createTbodyCells(records) {
tbody.textContent = ''
for (let i = 0; i < records.length; i++) {
let record = records[i]
let tr = document.createElement('tr')
for (const key in record) {
if (Object.hasOwnProperty.call(record, key)) {
let td = document.createElement('td')
td.textContent = record[key]
tr.append(td)
}
}
tbody.append(tr)
}
}
body {
background-color: rgb(235, 235, 235);
}
th{
background-color: black;
color: white;
}
td{
border: 1px solid black;
padding: .5rem;
}
button{
border: none;
padding: .5rem;
background-color: rgb(13, 118, 179);
color: white;
}
.container{
width: fit-content;
margin: auto;
}
.navigation{
width: fit-content;
margin: auto;
}
<div class="container">
<table data-record-start="0" data-record-end="">
<thead>
<tr>
</tr>
</thead>
<tbody>
</tbody>
</table>
<div class="navigation">
<button class="prev">Prev</button>
<button class="next">Next</button>
</div>
</div>
I assume you're getting an array of objects.
Here is a paginate function (vanilla js), which converts an array to -> an array of arrays
const paginate = (data) => {
const DATA_PER_PAGE = 5;
const TOTAL_USER_COUNT = data.length;
const PAGE_COUNT = Math.ceil(TOTAL_USER_COUNT / DATA_PER_PAGE);
const paginatedData = Array.from({ length: PAGE_COUNT }, (_, index) => {
const start = index * DATA_PER_PAGE;
return data.slice(start, start + DATA_PER_PAGE);
});
return paginatedData;
};
Now, the length of this array is the 'number of pages'. using this length you can dynamically generate buttons. Add event listener (I'd use event delegation and indexes(or maybe data-id)) and access the data you need (meaning that if the button clicked is index 0, then access 0th index on this array of arrays).
I want to add an external CSV file into a JOSN Array in my JS Code.
I tried lots of codes, with no luck like this:
var map = {};
var rows = csv.split(/\n/g);
var keys = rows.shift().split(",");
rows.forEach(raw_row => {
var row = {};
var row_key;
var columns = raw_row.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);
columns.forEach((column, index) => {
var key = keys[index];
if (!key) return;
if (key === 'Name') {
row_key = column;
return;
}
if (key === "Coordinates") {
column = column.replace(/""/g, '"');
column = column.substring(1, column.length - 1);
column = column.replace(/([a-zA-Z_]+):/g, `"$1":`);
try {
column = JSON.parse(`{${column}}`);
} catch (e) {}
}
row[key] = column;
});
map[row_key] = row;
});
console.log(map);
but I believe my expectation is something else, so I dont get what I want.
could some one pleae help me to change this csv(file):
contry;fromNr;toNr;Type;cust_1;cust_2
US;0;100;wood;max;nuk
DE;100;500;metal;max;pal
into JSON Array:
[{
"country": "US",
"fromNr": 0,
"toNr": 100,
"Type": "wood",
"cust_1": "max",
"cust_2": "nuk"
}, {
"country": "DE",
"fromNr": 100,
"toNr": 500,
"Type": "metal",
"cust_1": "max"
}]
You can use the below function csvIntoJson to convert.
const csv = 'contry;fromNr;toNr;Type;cust_1;cust_2\nUS;0;100;wood;max;nuk\nDE;100;500;metal;max;pal';
const csvIntoJson = (csv, separator) => {
let [headers, ...rows] = csv.split('\n');
headers = headers.split(separator);
rows = rows.map(row => row.split(separator));
return rows.reduce((jsonArray, row) => {
const item = row.reduce((item, value, index) => {
return {...item, [headers[index]]: value};
}, {});
return jsonArray.concat(item);
}, []);
};
const jsonArray = csvIntoJson(csv, ';');
My suggestion use a library, But you still want to understand how it can be done then here is the simple code.
I have used ',' delimiter, You can change it to ';' or anything else as per your usecase.
steps:
Read csv as text
split text by new line to get rows
split row by delimiter like ',' or ';'
Do your stuff
code:
function Upload(input){
console.log("uploading");
let file = input.files[0];
let reader = new FileReader();
reader.readAsText(file);
reader.onload = function() {
map_object = [];
console.log(reader.result);
var textByLine = (reader.result).split("\n")
console.log(textByLine);
// read header
header = (textByLine[0]).split(',');
// read data
for(var i = 1 ; i< textByLine.length -1; i++){
temp_row = {}
row_data = textByLine[i].split(',');
for (var j = 0 ; j< header.length; j++){
temp_row[header[j]] = row_data[j]
}
console.log(temp_row);
map_object.push(temp_row);
}
console.log(map_object);
document.write(JSON.stringify(map_object));
};
reader.onerror = function() {
console.log(reader.error);
};
}
<input type="file" id="fileUpload" accept='.csv' onchange="Upload(this)"/>
var data = "contry;fromNr;toNr;Type;cust_1;cust_2\nUS;0;100;wood;max;nuk\nDE;100;500;metal;max;pal";
function CSVtoJSON(csv) {
var lines = csv.split("\n");
var result = [];
var headers = lines[0].split(";");
for (var i = 1; i < lines.length; i++) {
var obj = {};
var currentline = lines[i].split(";");
for (var j = 0; j < headers.length; j++) {
obj[headers[j]] = currentline[j];
}
result.push(obj);
}
return result;
}
console.log(CSVtoJSON(data));
window.onload = function() {
var dataPoints = [];
// fetching the json data from api via AJAX call.
var X = [];
var Y = [];
var data = [];
function loadJSON(callback) {
var xobj = new XMLHttpRequest();
xobj.overrideMimeType("application/json");
xobj.open('GET', ' https://api.myjson.com/bins/cixax', true);
xobj.onreadystatechange = function() {
if (xobj.readyState == 4 && xobj.status == "200") {
callback(xobj.responseText);
}
}
xobj.send(null);
}
loadJSON(function(response) {
var response;
var field = JSON.parse(response);
var values = [];
//Iterating and storing leads & visits in a variable.
var $this = field;
for (var key in $this) {
if ($this.hasOwnProperty(key)) {
var data = $this[key].dates;
for (var val in data) {
values.push({
"X": data[val].visits,
"Y": data[val].leads
});
}
}
}
dataPoints = ({
"values": values
});
});
var chart = new CanvasJS.Chart("chartContainer", {
title: {
text: "Log Scale on Axis Y - Workaround using Linear Axis"
},
axisY: {
//valueFormatString: "0.## E0",
title: "In log scale",
labelFormatter: function(e) {
var lable = Math.pow(10, e.value);
if (lable >= 1000)
lable = CanvasJS.formatNumber(lable / 1000) + "k";
else
lable = CanvasJS.formatNumber(lable);
return lable;
},
interval: 1,
includeZero: false
},
toolTip: {
contentFormatter: function(e) {
var content = "Data Values";
for (var i = 0; i < e.entries.length; i++) {
content += "</br>" + e.entries[i].dataPoint.x + " : ";
content += CanvasJS.formatNumber(Math.round(Math.pow(10, e.entries[i].dataPoint.y)));
}
return content;
}
},
data: [{
type: "line",
dataPoints: []
}]
}); convertToLog(chart.options.data); chart.render();
function convertToLog(data) {
var dataPoints;
for (var j = 0; j < data.length; j++) {
dataPoints = data[j].dataPoints;
for (var i = 0; i < dataPoints.length; i++) {
dataPoints[i].y = Math.log10(dataPoints[i].y);
}
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<div id="chartContainer" style="height: 360px; width: 100%;"></div>
Here I am trying to draw the graph using canvasjs. I am getting the input from the external API using an AJAX call. And storing the variables X and Y in the array. Providing that as an input to that canvasjs library for drawing the graph. But I am not able to draw the graph. The above snippet is the one I have done.
The Chart wasn't getting rendered because the render method gets called before the data actually is loaded.
"x" & "y" should be in small instead of capital. The graph looks scrambled because the X Values in your JSON are not sorted.
Since the library now supports Logarithmic Scale on Y-Axis, you can use that instead of the work around.Here's a documentation link.
window.onload = function() {
//var dataPoints = [];
// fetching the json data from api via AJAX call.
var X = [];
var Y = [];
var data = [];
function loadJSON(callback) {
var xobj = new XMLHttpRequest();
xobj.overrideMimeType("application/json");
xobj.open('GET', 'https://api.myjson.com/bins/cixax', true);
xobj.onreadystatechange = function() {
if (xobj.readyState == 4 && xobj.status == "200") {
callback(xobj.responseText);
}
}
xobj.send(null);
}
loadJSON(function(response) {
var response;
var field = JSON.parse(response);
var values = [];
//Iterating and storing leads & visits in a variable.
var $this = field;
for (var key in $this) {
if ($this.hasOwnProperty(key)) {
var data = $this[key].dates;
for (var val in data) {
values.push({
"x": data[val].visits, // Should be "x" & "y"
"y": data[val].leads
});
}
}
}
//dataPoints = ({
// "values": values
//});
// Update the dataPoints & render the chart
// x values need to be in sorted order
chart.options.data[0].dataPoints = values;
chart.render();
});
var chart = new CanvasJS.Chart("chartContainer", {
title: {
text: "Log Scale on Axis Y - Workaround using Linear Axis"
},
axisY: {
//valueFormatString: "0.## E0",
title: "In log scale",
labelFormatter: function(e) {
var lable = Math.pow(10, e.value);
if (lable >= 1000)
lable = CanvasJS.formatNumber(lable / 1000) + "k";
else
lable = CanvasJS.formatNumber(lable);
return lable;
},
interval: 1,
includeZero: false
},
toolTip: {
contentFormatter: function(e) {
var content = "Data Values";
for (var i = 0; i < e.entries.length; i++) {
content += "</br>" + e.entries[i].dataPoint.x + " : ";
content += CanvasJS.formatNumber(Math.round(Math.pow(10, e.entries[i].dataPoint.y)));
}
return content;
}
},
data: [{
type: "line",
dataPoints: []
}]
}); //convertToLog(chart.options.data); chart.render();
function convertToLog(data) {
var dataPoints;
for (var j = 0; j < data.length; j++) {
dataPoints = data[j].dataPoints;
for (var i = 0; i < dataPoints.length; i++) {
dataPoints[i].y = Math.log10(dataPoints[i].y);
}
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<div id="chartContainer" style="height: 360px; width: 100%;"></div>
I'm trying to change the SelectionModel of a PivotGrid and it isn't working. Here is my code. Can someone tell what I am doing wrong.
I need to use a cellSelectionModel as I want to drill down and I need the top and left axis to get the intersection points.
I have also tried the 'cellclick' event in the EXTJS 3.3 API with no luck. Anyone get a selection model other than the default RowSelectionModel working?
var pivotAccumGrid = new Ext.grid.PivotGrid({
store : my_store,
aggregator: 'count',
measure : 'my_field',
sm: new Ext.grid.CellSelectionModel({ //I have also tried selModel for key
listeners: {
cellselect: function(sm,row,col) {
Ext.Msg.alert('click','got a click!');
}
}
}),
topAxis: [ {dataIndex: 'top_field'},{dataIndex: 'top_field2'} ],
leftAxis: [ {dataIndex: 'left_field', width: 80} ],
});
This is a quick fix that introduces a new property to meta in PivotGridView so it can later be used to back out the cell indices. Most of the code isn't any different, just the introduction of meta.id in renderRows and the splitting of meta.id in getCellIndex.
Ext.override(Ext.grid.PivotGridView, {
renderRows : function(startRow, endRow) {
var grid = this.grid,
rows = grid.extractData(),
rowCount = rows.length,
templates = this.templates,
renderer = grid.renderer,
hasRenderer = typeof renderer == 'function',
getCellCls = this.getCellCls,
hasGetCellCls = typeof getCellCls == 'function',
cellTemplate = templates.cell,
rowTemplate = templates.row,
rowBuffer = [],
meta = {},
tstyle = 'width:' + this.getGridInnerWidth() + 'px;',
colBuffer, column, i;
startRow = startRow || 0;
endRow = Ext.isDefined(endRow) ? endRow : rowCount - 1;
for (i = 0; i < rowCount; i++) {
row = rows[i];
colCount = row.length;
colBuffer = [];
rowIndex = startRow + i;
//build up each column's HTML
for (j = 0; j < colCount; j++) {
cell = row[j];
meta.id = i + '-' + j;
meta.css = j === 0 ? 'x-grid3-cell-first ' : (j == (colCount - 1) ? 'x-grid3-cell-last ' : '');
meta.attr = meta.cellAttr = '';
meta.value = cell;
if (Ext.isEmpty(meta.value)) {
meta.value = ' ';
}
if (hasRenderer) {
meta.value = renderer(meta.value);
}
if (hasGetCellCls) {
meta.css += getCellCls(meta.value) + ' ';
}
colBuffer[colBuffer.length] = cellTemplate.apply(meta);
}
rowBuffer[rowBuffer.length] = rowTemplate.apply({
tstyle: tstyle,
cols : colCount,
cells : colBuffer.join(""),
alt : ''
});
}
return rowBuffer.join("");
},
getCellIndex : function(el) {
if (el) {
var match = el.className.match(this.colRe),
data;
if (match && (data = match[1])) {
return parseInt(data.split('-')[1], 10);
}
}
return false;
}
});