Javascript Letter Frequency Graph Using Google Charts API [Homework] - javascript

I have this assignment to enter a sentence in the textarea and then output it as a HTML Frequency Chart and then output it using the Google Chart API.
I was able to output it as the HTML Frequency Chart but I am stuck on the Google Chart API part.
At the bottom in the generateApiTable() function, I know the value for the seperate columns is being retrieved by the data.join() part but if I remove that, then I don't get the letters being displayed on the bottom. The default value being put in is always 5.
I already tried taking the for loops from the generateTable() function and put them in the generateApiTable() function and then replaced data.join() with myHeight but that only displayed the letter 'A' on x-axis with value 25 (which is correct) but I need the entire alphabet.
So my question is how would I go about populating the Google Chart Api image with the frequency values previously gotten (for the HTML table).
var image = new Image();
var frequency = new Array(26);
var letters = new Array(26);
function html_chart()
{
var table = document.getElementById("table");
input = document.getElementById("user_input").value
table.innerHTML = generateTable(input);
}
function api_table()
{
var table = document.getElementById("api_table");
table.innerHTML = generateApiTable();
}
function getCharacterCounts()
{
letters = {}
for (i = 0; i < input.length; i++)
{
console.log(letters[input[i]])
if (letters[input[i]] >= 0)
letters[input[i]] += 1
else
letters[input[i]] = 0
}
return letters
}
function generateTable(input) {
var Pos = 0;
var max = 0;
var myHeight = 0;
var newInput = input.toUpperCase();
for (i = 65; i < 91; i++)
{
frequency[Pos] = newInput.split(String.fromCharCode(i)).length - 1;
Pos++;
}
for (i = 0; i < frequency.length - 1; i++)
{
if (frequency[i] > max) {
max = frequency[i];
}
}
table = input + '<table>';
table += "<tr>";
table += "<td>Letter Frequency 100px</td>";
for (i = 0; i < frequency.length; i++)
{
myHeight = (frequency[i] / max) * 100;
myHeight = parseInt(myHeight, 10);
table += '<td height = "100" width = "10"><img src = "orange.gif" alt = "25" height = "' + myHeight + '" width = "5"></td>';
}
table += "</tr>";
table += "<tr>";
table += "<td></td>";
for (i = 65; i < 91; i++)
{
table += "<td>" + String.fromCharCode(i) + "</td>";
}
table += "</tr>";
table += "</table>";
return table;
}
function generateApiTable()
{
labels = []
data = []
for (i = 65; i < 91; i++)
{
data.push(5)
labels.push(String.fromCharCode(i))
}
return '<img src = "http://chart.apis.google.com/chart?cht=bvs&chd=t:' + data.join() + '&chs=717x100&chl='+labels.join("|") + 'A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z&chxt=y" />'
}
function eraseText()
{
document.getElementById("user_input").value = "";
}
EDIT
Html Code
<html>
<body>
<form>
<textarea name = "text" style = "width:400px; height:200px" id = "user_input">The Quick Brown Fox Jumped Over The Lazy Dogs</textarea><br>
<input type = "button" value = "HTML Chart" onclick ="html_chart()">
<input type = "button" value = "Reset Test Data" onclick= "eraseText()">
<input type = "button" value = "Image Chart" onclick = "api_table()">
</form>
<div id = "table">
</div>
<div id = "api_table">
</div>
<style>
td {
vertical-align:bottom;
horizontal-align:left;
padding:0;
text-align: center;
background-color: lightgrey;
}
</style>
</body>
<script type = "text/javascript" src = "code.js"/>
</script>
</html>

Related

How can I change the order of the box numbers?

The order of the numbers in my box is as follows:
function boxNumbers(){
let boxes = document.querySelectorAll('.box')
boxes.forEach((box,i)=>{
if(String(i).length==1 || (String(i).length==2 && Number(String(i)[0]))%2==0){
//box.innerHTML = `${100-i}, i=${i}`
box.innerHTML = 100-i
}
else{
box.innerHTML = String(Number(`${9-Number(String(i)[0])}${String(i)[1]}`)+ 1)
}
})
}
how can I change it to look like this:
You can use this:
function boxNumbers() {
let boxes = document.querySelectorAll('.box');
let n = Math.sqrt(boxes.length);
[...boxes].reverse().forEach((box, i) => {
box.textContent = i % (n * 2) < n ? i + 1 : i + n - 2*(i % n);
})
}
With the assignment to n you make it a bit more generic -- still assuming your table is square. By reversing the iteration, you eliminate the need for the 100- subtraction. What remains is a formula that detects whether we're on a row with a reverse sequence or not, and adapts the number accordingly. The number "1" will always be in the bottom-right corner:
function boxNumbers() {
let boxes = document.querySelectorAll('.box');
let n = Math.sqrt(boxes.length);
[...boxes].reverse().forEach((box, i) => {
box.textContent = i % (n * 2) < n ? i + 1 : i + n - 2*(i % n);
})
}
// Utility to create the table
function fillTable(table, n) {
for (let i = 0; i < n; i++) {
let row = table.insertRow();
for (let j = 0; j < n; j++) {
let cell = row.insertCell();
cell.className = "box";
}
}
}
// Example run with n=5. Adapt as needed
let n = 5
fillTable(document.querySelector('table'), n);
boxNumbers();
table { border-collapse: collapse }
td { border: 1px solid ; width: 20px; height: 20px; text-align: center }
<table></table>
Here is a function which builds a bi-dimensional array and appends it as a table (row/col) to a dom element. You can adapt it to your template as you wish.
Works with any base number, yours is 5
function buildMatrix(baseNumber){
var flip = false;
var countDownNumber = baseNumber * baseNumber;
var currNumber = countDownNumber;
var matrix = "";
for(i = 0; i < baseNumber; i++) {
if(i !== 0){
currNumber = (flip)? countDownNumber + 1 - baseNumber : countDownNumber;
}
matrix += "<tr>";
for(j = 0; j < baseNumber; j++){
matrix += "<td>" + currNumber + "</td>";
// depending on the direction (flip) we increment or decrement
(flip)? currNumber++ : currNumber--;
countDownNumber--;
}
// change direction at the end of a row
flip = !flip;
matrix += "</tr>";
}
return matrix;
}
var baseSquareNumber = 11; // here you put 5
var matrixHtml = buildMatrix(baseSquareNumber);
document.getElementById("matrix").innerHTML = matrixHtml;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<table id="matrix">
</table>
</body>
</html>

How to embed a for-loop in a table in JavaScript?

I have to generate a sequence with a difference of 9. starting from 7. sequence should have 20 terms. I have tested my for loop and its working fine. Question is, how do I embedd this for loop in a table in javascript? Just want the table to have one column (sequence in for loop)
<script type="text/javascript">
var i;
var p;
for (i = 0; i < 20; i++) {
p = i * 9 + 7;
document.writeln(p + "<br>");
}
</script>
Use a loop to create the relevant HTML element objects and set their values within your Javascript:
var table = document.createElement("table");
var i;
var p;
for (i = 0; i < 20; i++) {
var row = document.createElement("tr");
var row_data = document.createElement("td");
p = i * 9 + 7;
row_data.innerHTML = p;
row_data.style = "border: 1px solid black";
row.appendChild(row_data);
table.appendChild(row);
}
document.body.appendChild(table);
Declare a table in html and give it an id
<table id="table"></table>
Then, get that table in your javascript and add one row, column in each iteration
<script type="text/javascript">
var i;
var p;
var table = document.getElementById("table");
for (i = 0; i < 20; i++) {
p = i * 9 + 7;
table.innerHTML = `${table.innerHTML}<tr><td>${p}</td></tr>`;
}
</script>
let table = '<table><tbody>';
for (let i = 0; i < 20; i++) {
table += (`<tr><td>${i}</td><td>${i * 9 + 7}</td></tr>`);
}
table += '</tbody></table>';
document.body.innerHTML = table;
Array.from(document.getElementsByTagName('td'))
.forEach((td) => {
td.style.border = '1px solid green';
td.style.width = '40px';
td.style.textAlign = 'right';
td.style.paddingRight = '20px';
});
Array.from(document.getElementsByTagName('table'))
.forEach((table) => {
table.style.border = '2px solid';
});

Change color of cells based on value in DB

I'm trying to accomplish the following.
I have a "grid" in which each cell can be 'owned' by a user.
To 'own' some new cells, the user should be able to click on two points (in a straight line) on the grid and then confirm by clicking on a button or cancel by clicking on another button, which updates the state of the grid. When both points are clicked, the cells between the two clicked ones must change color.
I should mention that I would like to achieve this only by using plain Javascript / PHP, if possible.
What I've done so far:
I have stored the 'grid' in a DB, having a record for each cell, containing position (i, j), owner and some other feature.
I query the DB using PHP, I save everything in memory (2D array - the grid is supposed to be small) and represent the grid by generating an HTML table
I'm trying to use JS to change the color of the cells when clicking, but I'm having problems (I'm new to JS and web programming in general).
I'm sure there's some kind of pattern to do what I want to do (surely is not rocket science), and would completely agree the following is pure Spaghetti code, but that's the only way I thought of doing it given my very very limited experience.
I do the following.
I have an HTML page with a named div in which I represent the table
<div id="Vis_table"> <?php echo $table ?> </div>
At the end of the body I have a script, which I report in its essential elements
var click = 0;
var grid = <?php echo json_encode($grid); ?>;
var Y_grid = <?php echo Y_g; ?>;
if (click == 0) { //first click
var cells = document.getElementsByTagName("th"); //take all cells
for (var i = 0; i < cells.length; i++) { // all rows
var row = parseInt(i / (Y_grid)); //dimensions
var col = i % (Y_grid);
cells[i].onclick = (function (xr, yc, index) {
return function () {
if (click == 0) { //first click, start
var tab = "<table>";
for (var x = 0; x < grid.length; x++) {
tab += "<tr>";
for (var y = 0; y < grid[0].length; y++) {
if (x == xr && y == yc) { //if it's the cell i clicked on
tab += "<th class = 'clicked'>" + x + " " + y + "</th>";
} else {
tab += "<th class = 'free'> </th>";
}
}
tab += "</tr>";
}
tab += "</table>";
click = 1;
document.getElementById("Vis_table").innerHTML = tab;
}
};
})(row, col, i);
}
}
Now, this works just fine, and the clicked cell changes color according to the CSS rules. The problem is that I don't know how to go on (ie color the cells between the first and the second clicked cells).
Do you have any suggestion?
Table prepared via JS(to do this in PHP is your task).
Area marking in JS :)
I've split the task in small steps to its easier to understand. If you got questions, feel free to ask!
/* This is generated by PHP (for testing i do it with js here) >>> */
var rows = 5;
var cols = 10;
var $table = $('#myTable');
for( let row = 1; row <= rows; row++ ) {
$row = $('<tr>');
for( let col = 1; col <= cols; col++ ) {
$col = $('<td>');
$col.text(row + "|" + col);
$col.attr('data-row', row);
$col.attr('data-col', col);
$row.append($col);
}
$table.append($row);
}
/* <<< */
var cells = [];
$('#myTable').click(function(e) {
$cell = $(e.target);
cells.unshift($cell);
if(cells.length > 2) {
cells.pop();
}
resetCells();
markActiveCells();
if ( cells.length == 2 ) {
fillArea();
}
});
function resetCells() {
$('#myTable td').removeClass('active');
$('#myTable td').removeClass('area');
}
function markActiveCells() {
$(cells).each(function() {
$(this).addClass('active');
});
}
function fillArea() {
if( cells.length < 2 ) return;
start_row_cell = (cells[0].data('row') <= cells[1].data('row'))?0:1;
start_col_cell = (cells[0].data('col') <= cells[1].data('col'))?0:1;
start_row = cells[start_row_cell].data('row');
end_row = cells[(start_row_cell+1)%2].data('row');
start_col = cells[start_col_cell].data('col');
end_col = cells[(start_col_cell+1)%2].data('col');
for( let row = start_row; row <= end_row; row++ ) {
for( let col = start_col; col <= end_col; col++ ) {
$('#myTable td[data-row=' + row + '][data-col=' + col + ']').addClass('area');
}
}
}
td {
font-size: 10px;
width: 25px;
height: 25px;
background-color: #EEE;
text-align: center;
}
td.active {
background-color: #FA0 !important;
}
td.area {
background-color: #FDA;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="myTable" cellspacing=0></table>

How to append multiplication result of 2 vars in table cells?

I'm prompting the user to enter a number for row and another for column, then construct a table using the given numbers and numbering each cell accordingly.
However, I want my final result to be displayed as a multiplication table, like the image below:
multiplication table image
And here's what my code looks like so far:
var table = document.getElementById("table");
var temp = "<table border = 1 border-collapse = collapse>";
for (var i = 0; i < row; i++){
temp += "<tr>";
if (i == 0){
for (var j = 0; j < column; j++){
temp += "<td height = 20 width = 40>" + (j+1) + "</td>";
}
} else{
for (var j = 0; j < column; j++){
temp += "<td height = 20 width = 40>" + (i+1) + "</td>";
}
}
temp += "</tr>";
}
temp += "</table>";
table.innerHTML=temp;
That is nearly right already. What you are looking for is to put (i+1)*(j+1) in the second for statement.
I'm not sure how you get your user input. Prompt is not usually a great way to get input but because you said that's what you used the example below uses prompt. The problem with it is that it blocks everything else: not only your own webpage, but the entire browser. If you have not done so already, you might consider getting your user-inputted numbers from an HTML form.
You might also want input checking code. I've included it below in a full HTML/JS solution. It gives the user 3 chances to enter a number for both the row and the column. If the user fails to do so, it outputs an error message.
<html>
<head>
</head>
<body>
<div id='table'></div>
<script>
var table = document.getElementById('table');
var attemptCounter = 0;
var maxAttempts = 2;
var temp='<table border = 1 border-collapse = collapse>';
var row;
var column;
while ((typeof row !=='number' || attemptCounter <= maxAttempts) && isNaN(row) ){
var row = parseInt(prompt("Please enter the number of ROWS for your table:"),10);
if(typeof row ==='number' && !isNaN(row)){break;};
attemptCounter++;
}
if(attemptCounter >= maxAttempts+1){
table.innerHTML = 'Error: expected NUMBER for number of rows';
}
if(attemptCounter < maxAttempts+1){
attemptCounter = 0;
while ((typeof column !=='number' || attemptCounter <= maxAttempts) && isNaN(column) ){
var column = parseInt(prompt("Please enter the number of COLUMNS for your table:"),10);
if(typeof column ==='number' && !isNaN(column)){break;};
attemptCounter++;
}
if(attemptCounter < maxAttempts+1){
for (var i = 0; i < row; i++){
temp += "<tr>";
if (i == 0){
for (var j = 0; j < column; j++){
temp += "<td height = 20 width = 40>" + (j+1) + "</td>";
}
} else {
for (var j = 0; j < column; j++){
temp += "<td height = 20 width = 40>" + (i+1)*(j+1) + "</td>";
}
}
temp += "</tr>";
}
temp += "</table>";
table.innerHTML=temp;
} else {
table.innerHTML = 'Error: expected NUMBER for number of columns';
}
}
</script>
</body>
</html>
Your code nearly works. If you change your (i+1) and (j+1) to (i * j) you'll see that the table created works, except for the first row and first column (as multiplying by 0 will always give 0).
However to deal with the multiplication with 0 in the first column and row there needs to be some conditional that checks if one of the values (either i or j are 0) and then changes the value to 1.
I've only changed what happens in your for loop.
for (var i = 0; i < row; i++){
temp += "<tr>";
for (var j = 0; j < column; j++){
// Here I have split your temp string.
temp += "<td height = 20 width = 40>";
if (i == 0 && j ==0){ // if both i and j are 0 then add a 0 to temp.
temp += 0;
} else {
// Multiply them together changing 0 to 1 (solving the 0's problem)
temp += (i == 0 ? 1 : i) * (j == 0 ? 1 : j);
}
temp += "</td>";
}
temp += "</tr>";
}
temp += "</table>";
table.innerHTML=temp;
i==0?1:i is a ternary operator which is just like a little if statement. It checks if i is 0 and if it evaluates to true it returns 1, otherwise it returns the value of i. Read more about it here
Putting it all together,
temp += (i==0?1:i) * (j==0?1:j) multiplies the values in the table together and also prevents multiplication with 0 in the headings.
Build HTML as string is not bad but it is better to work with DOM model. Here is an example.
<!DOCTYPE html>
<html>
<head>
<title>Build Table</title>
<meta charset="utf-8" />
<style type="text/css">
.tbl{border:solid 1px #ccc}
.tbl tr:first-child td,
.tbl td:first-child{background:#ccc;padding:4px}
</style>
<script type="text/javascript">
'use strict';
function buildTable() {
//get numbers from micro-form
var rows = document.getElementById('rows').value;
var cols = document.getElementById('cols').value;
//create table
var tbl = document.createElement('table');
tbl.className = 'tbl';//it is better then inline style
//note that HTML table has its own DOM model
var tr = tbl.insertRow(-1);//insert new row
//first row is special
tr.insertCell(-1).innerHTML = 'X';
//so treat it accordingly
for (var i = 1; i < cols; i++) {
tr.insertCell(-1).innerHTML = i;//insert new cell and set value inside
}
//remaining rows
for (i = 1; i < rows; i++) {
tr = tbl.insertRow(-1);
//first column is special
tr.insertCell(-1).innerHTML = i;
for (var j = 1; j < cols; j++) {
tr.insertCell(-1).innerHTML = i * j;
}
}
//well done. Place our table in a container
document.getElementById('table').appendChild(tbl);
}
</script>
</head>
<body>
<div>
Rows: <input type="number" id="rows" min="2" max="10" value="10" />
Columns: <input type="number" id="cols" min="2" max="10" value="10" />
<button onclick="buildTable()">Build Table</button>
</div>
<div id="table"></div>
</body>
</html>

How to populate a table with vertical and horizontal results?

HeaderA HeaderB HeaderA HeaderB
stuff 232 hey 3434
world 033 boy 221
bat 435 girl 930
This table is dynamic and gets populated live. Here's my JS code, but the logic is not working correctly. I need to tell it that every 2 columns is a new record, and make a new row every 4th column. Here's what I have so far:
function html_data(data) {
var html = '';
$.each(data, function (index, value) {
if ((index+1) % 4 == 0 && index != 0) {
html += '<td>'+value+'</td>';
html += '</tr>'
} else if ((index+1) % 5 == 0) {
html += '<tr>';
html += '<td>'+value+'</td>';
} else {
html += '<td>'+value+'</td>';
}
html += '</tr>';
});
return html;
}
Obviously the above code is completely wrong, but that's all I have so far. If I can the get the mod logic, I can fill in the blanks.
Try this http://jsfiddle.net/G3JK5/
HTML
<table id="table">
<tr>
<th>HeaderA</th>
<th>HeaderB</th>
<th>HeaderA</th>
<th>HeaderB</th>
<th>HeaderA</th>
<th>HeaderB</th>
</tr>
</table>
<input type="button" id="btn" value="Add some random data" />
Javascript
//Sample usage
var tbl = new weirdTable('table');
document.getElementById('btn').addEventListener('click', function(){
tbl.addData([
parseInt(Math.random() * 100),
parseInt(Math.random() * 100)
]);
});
weirdTable
function weirdTable(tableId){
var _me = null;
var _currentIndex = 0;
var _colCount = 0;
var _lastRowIndex = 0;
var construct = function(tableId){
_me = document.getElementById(tableId);
_colCount = _me.rows[0].cells.length;
_currentIndex = _colCount;
};
this.addData = function(data){
var row = _me.rows[_lastRowIndex];
//or var data = arguments;
for(var i = 0; i < data.length; i++){
if(_currentIndex >= _colCount){
_lastRowIndex++;
_currentIndex = 0;
row = _me.insertRow(_lastRowIndex);
}
row.insertCell(_currentIndex).innerText = data[i];
_currentIndex++;
}
};
construct(tableId);
}
Unless I'm missing something, you can just do this:
if (index%4===0) { // start of a row
html += '<tr>';
}
html += '<td>'+value+'</td>';
if (index%4===3) { // end of row
html += '</tr>';
}

Categories