Udacity pixel art lab - javascript

So I am trying to solve a lab that requires to build a color picker and a grid. By clicking on a particular cell, it gets colored with the color you picked. I passed 4/5 tests, the test that fails gives me: App functionality Picking a new color and clicking a cell displays the new color.
Even though when I test it, it works, I can change the color of cells.
javaScript Code:
// Select color input
var color;
function selectColor()
{
color = document.getElementById("colorPicker").value;
}
// Select size input
var height;
var width;
// When size is submitted by the user, call makeGrid()
var s = document.getElementById("sizePicker");
s.addEventListener('submit',function makeGrid(e)
{
e.preventDefault();
var height = parseInt(document.getElementById("inputHeight").value);
var width = parseInt(document.getElementById("inputWidth").value);
var t = document.getElementById("pixelCanvas");
while(t.firstChild)
{
t.removeChild(t.firstChild);
}
for(var i = 0;i < height; i++)
{
var r = document.createElement("tr");
t.appendChild(r);
for(var j = 0; j < width; j++)
{
var c = document.createElement("td");
r.appendChild(c);
}
}
var pixel = document.querySelectorAll("td");
pixel.forEach(myfunction);
function myfunction(item,index)
{
selectColor();
item.addEventListener('click', function(evt){
evt.preventDefault();
item.style.backgroundColor = color;})
}
})
Html code:
<!DOCTYPE html>
<html>
<head>
<title>Pixel Art Maker!</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Monoton">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Lab: Pixel Art Maker</h1>
<h2>Choose Grid Size</h2>
<form id="sizePicker">
Grid Height:
<input type="number" id="inputHeight" name="height" min="1" value="1"> Grid Width:
<input type="number" id="inputWidth" name="width" min="1" value="1">
<input type="submit">
</form>
<h2>Pick A Color</h2>
<input type="color" id="colorPicker" oninput="selectColor()">
<h2>Design Canvas</h2>
<table id="pixelCanvas" border = 1>
</table>
<script src="designs.js"></script>
</body>
</html>
codepen:
https://codepen.io/AMMAROVA/pen/QWQPLVJ
This is my first question on this website so excuse me if it wasn't clear enough.

Related

Creating a table using JavaScript

I am new to front-end web development and right now I am working on a test task to create a table using javascript.Here is my html file:
<title>Pixel Art Maker!</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Monoton">
<link rel="stylesheet" href="styles.css"> </head> <body>
<h1>Lab: Pixel Art Maker</h1>
<h2>Choose Grid Size</h2>
<form id="sizePicker">
Grid Height:
<input type="number" id="inputHeight" name="height" min="1" value="1">
Grid Width:
<input type="number" id="inputWeight" name="width" min="1" value="1">
<input type="submit" onclick="makeGrid()">
</form>
<h2>Pick A Color</h2>
<input type="color" id="colorPicker">
<h2>Design Canvas</h2>
<table id="pixelCanvas"></table>
<script src="designs.js"></script> </body> </html>
And my javascript file:
function makeGrid() {
var rows=inputHeight; var cols=inputWeight; //Referencw for the body var body=document.getElementsbyTagName("body")[0];
//create a table element and a <tbody> element var table1=document.createElement("table"); var tableBody=document.createElement("tbody");
//creating cells for (var i=0;i<rows;i++){ //creating a table row var R=document.createElement("tr"); for(var j=0;j<cols;j++){ //create a table data element var C=document.createElement("td"); R.appendchild(C);
} //adding the row to the end of the table body
tableBody.appendChild(R); } //putting the <tbody> in the <table> table1.appendChild(tableBody); //appending <table> into <body> body.appendChild(table1);
}
I am supposed to get user input of rows and columns via submit button and generate a table according to that specification.So far my attmepts are unsuccessful,more precisely when I hit submit,nothing happens and the values revert back to "1".
I would really appreciate your guidance and feedback.
You don't need a <form>. There's nothing to submit to.
Use document.getElementById
You already have a <table id> in HTML. Reference it!
You don't need therefore a document.body reference.
To retrieve the integer use parseInt( number, radix ) since input value is a String
Clear your table from existing content before appending new stuff.
Use addEventListener(EventName, callback) instead of inline JavaScript (onclick)
Weight is not Width!
function makeGrid() {
var ELTable = document.getElementById("pixelCanvas"); // You already have it!
var ELInputHeight = document.getElementById("inputHeight");
var ELInputWidth = document.getElementById("inputWidth");
var rows = parseInt(ELInputHeight.value, 10);
var cols = parseInt(ELInputWidth.value, 10); // Weight? you mean Width!
ELTable.innerHTML = ""; // Empty table before inserting new stuff
var tbody = document.createElement("tbody");
for (var i = 0; i < rows; i++) { // N rows...
var R = document.createElement("tr"); // Make row.
for (var j = 0; j < cols; j++) { // N cells...
var C = document.createElement("td"); // Make cell.
R.appendChild(C); // Insert cell into row.
}
tbody.appendChild(R); // Insert row into tbody
}
ELTable.appendChild(tbody); // Insert tbody into table
}
document.getElementById("makeGrid").addEventListener("click", makeGrid);
td { padding:10px; background:#000; }
Height: <input type="number" id="inputHeight" min="1" value="1">
Width: <input type="number" id="inputWidth" min="1" value="1">
<button id="makeGrid">MAKE</button>
<br>
Color: <input type="color" id="colorPicker">
<table id="pixelCanvas"></table>
I create function for generate body of table, and listener for butto
function createTableBody(height, width) {
let tr = document.createElement('tr');
let td = document.createElement('td');
let docFr = new DocumentFragment();
for (let i = 0; i < width; i++) {
tr.append(td.cloneNode());
}
for (let i = 0; i < height; i++) {
docFr.append(tr.cloneNode(true));
}
return docFr;
}
let table = document.getElementById('pixelCanvas');
let createTableButton = document.getElementById('createTableButton');
let inputHeight = document.getElementById('inputHeight');
let inputWidth = document.getElementById('inputWeight');
createTableButton.addEventListener('click', () => {
let parentTable = table.parentNode;
let tableClone = table.cloneNode();
parentTable.replaceChild(tableClone, table);//clear old table
table = tableClone;
tableClone.append(createTableBody(inputHeight.value, inputWidth.value));
// if you need , you can add ajax request
console.log(table)
});
<title>Pixel Art Maker!</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Monoton">
<link rel="stylesheet" href="styles.css"> </head> <body>
<h1>Lab: Pixel Art Maker</h1>
<h2>Choose Grid Size</h2>
Grid Height:
<input type="number" id="inputHeight" name="height" min="1" value="1">
Grid Width:
<input type="number" id="inputWeight" name="width" min="1" value="1">
<input type="button" id="createTableButton">
<h2>Pick A Color</h2>
<input type="color" id="colorPicker">
<h2>Design Canvas</h2>
<table id="pixelCanvas"></table>
</body> </html>
If you need send data to server, you can use ajax, and i replace your submit to button, remove form.
Try this:
<form id="form-grid" method="post" onsubmit="makeGrid()">
<h2 id="grid-size">Choose Grid Size</h2>
<label for="inputHeight">Grid height:</label>
<input type="number" id="inputHeight" name="height" min="1" value="1" aria-describedby="grid-size" />
<label for="inputWeight">Grid width:</label>
<input type="number" id="inputWeight" name="width" min="1" value="1" aria-describedby="grid-size" />
<h2>Pick a color</h2>
<label for="colorPicker">Color:</label>
<input type="color" id="colorPicker" name="color" />
<input type="submit" value="Make Grid" />
</form>
<div id="pixelCanvas"></div>
Do note the addition of explicit label's here. These are important for accessibility!
I've added a submit handler to the form, and removed it from the button. I find it's a bit cleaner, but your approach would ultimately work too.
Then in your designs.js file, you might have:
function makeGrid(event) {
event.preventDefault(); // prevents the form from submitting
var form = document.querySelector('#form-grid');
var rows = form.querySelector('#inputHeight').value;
var cols = form.querySelector('#inputWeight').value;
var wrapper = document.querySelector('#pixelCanvas');
var table = document.createElement('table');
for (var r = 0; r < rows; r++) {
var tr = table.insertRow();
for (var c = 0; c < cols; c++) {
var td = tr.insertCell();
}
}
wrapper.appendChild(table);
}
A few reminders:
Use label to associate a form field with it's visible label. This is necessary for assistive technology such as screen readers.
Consider a fieldset to group all of the options, increasing its accessibility.
Good luck!
As #Katamari said, it looks like you're not properly accessing the elements and getting their values.
To access an element, you can use document.querySelector and pass in a CSS selector.
var rowInput = document.querySelector("#inputHeight");
var colInput = document.querySelector("#inputWidth");
Since you have assigned IDs, you could use document.getElementById
var rowInput = document.getElementById("inputHeight");
var colInput = document.getElementById("inputWidth");
Either way, you'll get an element or null if the element can't be found. Once you have the element, just get the value property to get the user results.
var rows = rowInput.value;
var cols = colInput.value;
If you want to avoid error that could be caused by not finding the element, you can check for the element before referencing the value.
var rows = 1;
var cols = 1;
if (rowInput) {
rows = rowInput.value;
}
if (colInput) {
cols = colInput.value;
}
This can be converted into a single line using a tenary operator
var rows = rowInput
? rowInput.value
: 1;
var cols = colInput
? colInput.value
: 1;

To use the data from input tag in html in javascript

I want to use the data from input tags in html. The html code is shown below.
<form id="sizePicker">
Grid Height:
<input type="number" id="input_height" name="height" min="1" value="1">
Grid Width:
<input type="number" id="input_width" name="width" min="1" value="1">
<input type="submit">
The data values from input tags should be used in javascript code shown below:
function makeGrid() {
for(let td_row=0; td_row < 6; td_row++){
$(<tr></tr>).appendTo(<table id="pixel_canvas"></table>);
for(let td_cell =0; td_cell < 6; td_cell++){
$(<td></td>).appendTo(<tr></tr>);
}
}
Can somebody please help me in this?
Try this solution. Get the values from the inputs and set them as the range for the conditions in the loops. Then add your create tr in the first loop, in the second one append td to it. After all append the tr with tds to the table.
const table = $('#pixel_canvas');
const inputHeight = $('#input_height');
const inputWidth = $('#input_width');
function makeGrid() {
const height = parseInt(inputHeight.val());
const width = parseInt(inputWidth.val());
for(let row = 0; row < height; row++) {
const tr = $('<tr></tr>');
for(let cell = 0; cell < width; cell++) {
tr.append(`<td>${row}${cell}</td>`);
}
table.append(tr);
}
}
$('#submitBtn').on('click', makeGrid);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="sizePicker">
Grid Height:
<input type="number" id="input_height" name="height" min="1" value="1">
Grid Width:
<input type="number" id="input_width" name="width" min="1" value="1">
<button id="submitBtn" type="button">Generate</button>
<table id="pixel_canvas">
</table>
You need to use strings, when creating HTML element (e.g. $('')) instead of raw markup. I updated the function from the question, so that it creates a table and returns it. You only need to insert it wherever you need.
function makeGrid() {
var rowsCount = ParseInt($('#input_height').val()) || 0;
var columnsCount = ParseInt($('#input_width).val()) || 0;
var table = $('<table id="pixel_canvas"></table>');
for(let td_row = 0; td_row < rowsCount; td_row++){
var tr = $('<tr></tr>').appendTo(table);
for(let td_cell = 0; td_cell < columnsCount; td_cell++){
$('<td></td>').appendTo(tr);
}
}
return table;
}

Having trouble displaying output

This might sound like a simple thing for you programmers out there but i can't seem to figure it out. I'm making a program that where among 4 numbers the largest is outputted. I've got the core code working but i can't seem to think how i can display the results on the screen. I would like it so that when the user types a number into a text box the result appears in another text box at the press of a button. Thanks for your time & help.
HTML
<html>
<head>
<meta charset="UTF-8">
<script src="Main.js" type="text/javascript"></script>
<link href="Main.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<form id="Awesome">
<label>Input Numbers Here: </label><input type="text"
id="txtBox">
<br><br>
<label>Dec to Roman #: </label><input type="text" id="Results">
<br><br>
<input type="button" value="Calculate" id="Execute"
onclick="largestOfFour()">
</form>
</body>
</html>
Javascript
function largestOfFour(arr) {
var largestNumbers = [];
var currentLargest;
for (var x =0; x <arr.length; x++) {
currentLargest = 0;
for (var y = 0; y < arr [x].length; y++) {
if (arr[x][y] > currentLargest) {
currentLargest = arr[x][y];
}
}
largestNumbers.push(currentLargest);
}
return largestNumbers;
document.getElementById('Results').value = largestNumbers;
}
After entering the numbers in an input box, we can read its value as a string. Splitting that string with a space give us the numbers array. We will compare each number in that array to each other and save the biggest number in largest. Then we display its value in a Result box.
function largestOfFour() {
// get string from the input
var s = document.getElementById('txtBox').value;
var numbers = s.split(' ');
var largest = 0;
for (var x = 0; x < numbers.length; x++) {
var current = parseInt(numbers[x])
if (current > largest)
largest = current;
}
// display the largest number
document.getElementById('Results').value = largest;
}
<form id="Awesome">
<label>Input 4 Numbers (space separated): </label>
<input type="text" id="txtBox">
<br><br>
<label>Max #: </label>
<input type="text" id="Results" readonly>
<br><br>
<input type="button" value="Calculate" id="Execute" onclick="largestOfFour()">
</form>

Change a background color from frames to new window

I wanted to change background color of new window by selecting from frame. If we select any one of radio button, one new window has to open, and that window background color should be the selected button color. can anyone help me how to solve this..I don't know where i am going wrong.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
</head>
<title> Frames and Window </title>
<script>
function openWindowWithColor() {
var color = this.getAttribute("data-color");
console.debug("Open new window with color: " + color);
var myNewWindow = window.open();
myNewWindow.document.body.style.background = color;
}
var radios = document.getElementsByTagName("input");
for(var i = 0; i < radios.length; i++) {
radios[i].addEventListener("change", openWindowWithColor);
}
</script>
<body>
<p style="color:red ; font-size:15pt"> Choose the background color for new window:
</p>
</br></br>
<label for="red">Red</label>
<input type="radio" id="red" name="windowcolor" data-color="red" />
<label for="green">Green</label>
<input type="radio" id="green" name="windowcolor" data-color="green" />
<label for="blue">Blue</label>
<input type="radio" id="blue" name="windowcolor" data-color="blue" />
<br></br>
<input type="button" id = "submit" name="" style="color: green; font-size:20pt" value="submit" size ="10" onclick="openWindowWithColor()"/>
</body>
</html>
Try changing this line
myNewWindow.document.body.style.backgroundColor = color;
Hope it helps!
Change the javascript to this and it should work:
function openWindowWithColor() {
var color = this.getAttribute("data-color");
console.debug("Open new window with color: " + color);
var myWindow = window.open("", "", "width=200,height=100");
myWindow.document.body.style.backgroundColor = color;
}
var radios = document.getElementsByTagName("input");
for(var i = 0; i < radios.length; i++) {
radios[i].addEventListener("change", openWindowWithColor);
}
It will open a 200x100px window with the selected color.

Convert Miles to Kilometers in a range given by the user and display them in a list

I am required to write the code using three files, Javascript, HTML, and CSS. I am not sure what is the problem in my code, please help me find the error. The user is to write the range in two textareas and when a button is clicked convert all values starting from the first given number up to the second given number. This is what I have written so far:
HTML code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<link rel="stylesheet" type="text/css" href="../css/converter.css"/>
<title>Celsius to Fahrenheit Converter</title>
<script language="JavaScript" src="../js/c2f.js" type="text/javascript">
</script>
</head>
<body>
<h2>Miles to Kilometers Converter</h2>
<form action="">
<p>
<textarea rows="1" name="Input1" id="Input1" cols="10"></textarea>
<textarea rows="1" name="Input2" id="Input2" cols="10"></textarea>
<input type="button" value="Convert" name="B3" onclick="conversionTable()">
<input type="reset" value="Clear" name="B2">
</p>
</form>
<div id="conversion">
</div>
</body>
</html>
JavaScript code:
function conversionTable(tagId, from, to)
{
var first = document.getElementById("Input1");
var second = document.getElementById("Input2");
from =first;
to = second;
var conv = document.getElementById(tagId);
var tab = document.createElement("table");
var bod = document.createElement("tbody");
var thed = document.createElement("thead");
tab.appendChild(thed);
tab.appendChild(bod);
var tr = document.createElement("tr");
thed.appendChild(tr);
var th = document.createElement("th");
tr.appendChild(th);
th.appendChild(document.createTextNode("Miles"));
th = document.createElement("th");
tr.appendChild(th);
th.appendChild(document.createTextNode("Kilometers"));
conv.appendChild(tab);
for(var i=from; i<=to; i++){
tr = document.createElement("tr");
if (i%2==0)
tr.setAttribute("class", "even");
else
tr.setAttribute("class", "odd");
bod.appendChild(tr);
td = document.createElement("td");
tr.appendChild(td);
td.appendChild(document.createTextNode(i));
td = document.createElement("td");
tr.appendChild(td);
td.appendChild(document.createTextNode(c2f(i)));
}
function c2f(c) {return Math.round((c * 1.6093)*10)/10}
}
CSS code:
h2{text-align:center; color:blue; background: #EFEFEF}
body{margin: 4em; width: 400px}
table{margin: 2em; padding: 1em;}
th{background: #EFEFFF}
tr.even {background: #B8B8B8}
tr.odd {background: #E0FFFF}
So again, I am trying to pass the two variables (first and second) into my conversionTable() function.
DEMO HERE
Changes to your html:
<input type="button" value="Convert" name="B3" onclick="conversionTable('conversion')" />
Changes to your js:
from = parseInt(first.value);
to = parseInt(second.value);
and thats it. It should work to what you're looking for.
An exmaple of using plain javascript to build the conversion table:
<form action="">
<p>
<textarea rows="1" name="Input1" cols="10"></textarea>
<textarea rows="1" name="Input2" cols="10"></textarea>
<input type="button" value="Convert" name="B3" onclick="buildConversionTable(this);">
<input type="reset" value="Clear" name="B2">
</p>
</form>
<div id="conversion"></div>
<script>
// Convert miles to kilometres, round to 2 places
function m2k(c) {
return (c * 1.6093).toFixed(2); // returns a string
}
// Return a new element with provided tag name and properties
function newElement(tagName,props) {
var el = document.createElement(tagName);
if (props) {
for (var prop in props) {
if (props.hasOwnProperty(prop)) {
el[prop] = props[prop];
}
}
}
return el;
}
// Return a new text node with text as content
function newText(text) {
return document.createTextNode(text);
}
// Create the conversion table
function buildConversionTable(button) {
var form = button.form;
var from = form.Input1.value;
var to = form.Input2.value;
// Use a temporary element to build the tabel from HTML
var d = document.createElement('div');
d.innerHTML = '<table><thead><tr><th>Miles<th>Kilometres</thead></table>';
var table = d.getElementsByTagName('table')[0];
// Tables always have at least one tbody, no need for tags in the HTML
var tbody = table.tBodies[0]
// Use the convenience of appendChild returning the appended element
for (var i=from, row, cell; i<=to; i++) {
row = tbody.appendChild(newElement('tr',{className: i%2? 'odd':'even'}));
cell = row.appendChild(newElement('td'));
cell.appendChild(newText(i));
cell = row.appendChild(newElement('td'));
cell.appendChild(newText(m2k(i)));
}
// Add the table to the document
document.getElementById('conversion').appendChild(table);
}
</script>
Oh, forgot about the DOM table methods. The for loop adding the rows can be:
for (var i=from, row, cell; i<=to; i++) {
row = tbody.insertRow(-1);
row.insertCell(-1);
row.insertCell(-1);
row.className = i%2? 'odd':'even';
row.cells[0].innerHTML = i;
row.cells[1].innerHTML = m2k(i);
}
I would recommend using jQuery to solve this problem. To include jquery in your project change your html to this:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<link rel="stylesheet" type="text/css" href="../css/converter.css"/>
<title>Celsius to Fahrenheit Converter</title>
<script language="JavaScript" src="../js/c2f.js" type="text/javascript">
</script>
<!-- Here is your jquery code includer -->
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
</head>
<body>
<h2>Miles to Kilometers Converter</h2>
<form action="">
<p>
<textarea rows="1" name="Input1" id="Input1" cols="10"></textarea>
<textarea rows="1" name="Input2" id="Input2" cols="10"></textarea>
<input type="button" value="Convert" id="convert" name="B3" />
<input type="reset" value="Clear" name="B2" />
</p>
</form>
<div id="conversion"></div>
</body>
</html>
Using jQuery you can add the click handler to the convert button and in there calculate the from and to and call the conversionTable function. I have revised the conversionTable function to do what you want in much less code using jQuery.
$("#convert").click(function () {
var from = parseInt($("#Input1").val());
var to = parseInt($("#Input2").val());
conversionTable($("#conversion"), from, to);
});
function conversionTable(tag, from, to) {
//Generate the table with the thead of miles and kilometers
var table = $("<table><thead>" +
"<tr><th>Miles</th><th>Kilometers</th></tr>" +
"</thead><tbody></tbody></table>");
//set the tags innerHtml to the table
tag.html(table);
for (var i = from; i <= to; i++) {
var miles = i;
var kilometers = c2f(i);
//Create a tr with the found miles and kilometers
var tr = $("<tr><td>" + miles + "</td><td>" + kilometers + "</td></tr>");
//Add the tr to the tables tbody
table.find("tbody").append(tr);
}
//Find all of the even and odd tr's and give them the appropriate class
table.find("tr:even").addClass("even");
table.find("tr:odd").addClass("odd");
function c2f(c) {
return Math.round((c * 1.6093) * 10) / 10;
}
}
Your css would stay the same as previously posted. You can find a working jsFiddle at http://jsfiddle.net/FsV3j/.

Categories

Resources