How to implement a seat reservation application into Google Sites - javascript

I found this example here on Stack Overflow which is exactly what I was looking for:
https://stackoverflow.com/a/40013027/1955916
I tried several approaches to include this code in to Google Sites. I tried with an HTML gadget, directly as HTML and as JavaScript gadget. But so far nothing worked.
Based on the example of user Grant: document.getelementbyId in Google Script not working I think I am on a promising way, but it still does not work.
I have stored the following script in Google sites and published it as a web app. Then I included it as a Apps Script Gadget in my testpage.
However, the only thing that is displayed is the Title. So I must have a fundamental error somewhere, but my current knowledge is really limited here.
Code.gs:
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('Index');
}
Index.html:
<!DOCTYPE html>
<html>
<head>
<title>Demo of a canvas used to render seat plan in a Cinema</title>
<script>
var EMPTY = 0; // Still available for reservation and purchase.
var RESERVED = 1; // reserved but not yet paid for.
var BOUGHT = 2; // bought and paid for.
function Point(x,y) {
return { X: x, Y: y }
}
function Size(w,h) {
return {Width: w, Height: h}
}
function Rectangle(left,top,width,height) {
return {TopLeft: Point(left,top), Size: Size(width,height)}
}
function seatColorFromSeatStatus(seatStatus) {
switch(seatStatus) {
case EMPTY: return "white";
case RESERVED: return "green";
case BOUGHT: return "red";
default: return "black"; // Invalid value...
}
}
function mapSeatStatusToSeatColor(seats)
{
var result = {};
for(seat in seats) {
result[seat] = seatColorFromSeatStatus(seats[seat])
}
return result;
}
function seatKeyFromPosition(row,col) {
return JSON.stringify([row,col]);
}
function seatRowFromKey(key) {
return (JSON.parse(key))[0];
}
function seatColFromKey(key) {
return (JSON.parse(key)[1]);
}
function getSeatInfo(nrows,ncolumns) {
var result = { NRows: nrows, NColumns: ncolumns, Seats : {} };
for(row = 0; row < nrows; row++) {
for( col = 0; col < ncolumns; col++ ) {
result.Seats[seatKeyFromPosition(row,col)] = EMPTY;
}
}
result.Seats[seatKeyFromPosition(0,0)] = RESERVED;
result.Seats[seatKeyFromPosition(1,3)] = BOUGHT;
return result;
}
function renderSeat(ctx,r,fillColor) {
var backup = ctx.fillStyle;
ctx.strokeStyle = "blue";
ctx.rect(r.TopLeft.X+2,r.TopLeft.Y+2,r.Size.Width-4,r.Size.Height-4);
ctx.stroke();
ctx.fillStyle = fillColor;
ctx.fillRect(r.TopLeft.X+3,r.TopLeft.Y+3,r.Size.Width-5,r.Size.Height-5);
ctx.fillStyle = backup;
}
function renderSeatplan(seatInfo) {
var nrows = seatInfo.NRows;
var ncolumns = seatInfo.NColumns;
var seatColors = mapSeatStatusToSeatColor(seatInfo.Seats)
var canvas = document.getElementById("seatplan");
var ctx = canvas.getContext("2d");
var borderWidth = 10;
var rcContent = Rectangle(
borderWidth
, borderWidth
, canvas.width - 2 * borderWidth
, canvas.height - 2 * borderWidth
);
var szCell = Size(
Math.floor(rcContent.Size.Width / (ncolumns + 1))
, Math.floor(rcContent.Size.Height / (nrows + 1))
);
ctx.font = "30px Arial";
for(row = -1; row < nrows; row++) {
for(col = -1; col < ncolumns; col++ ) {
var r = Rectangle(
rcContent.TopLeft.X + szCell.Width * (col+1)
,rcContent.TopLeft.Y + szCell.Height * (row+1)
,szCell.Width
,szCell.Height
);
var center = Point(szCell.Width / 2, szCell.Height / 2);
if (row == -1 && col == -1) {
// nothing to render.
}
else if(row == -1){
// render column headers as numbers...
ctx.fillStyle = "black";
ctx.textAlign = "center";
ctx.fillText(col.toString(),r.TopLeft.X+center.X,r.TopLeft.Y+center.Y+6);
}
else if(col == -1){
// render row header
ctx.fillStyle = "black";
ctx.textAlign = "center";
ctx.fillText(String.fromCharCode(65 + row),r.TopLeft.X+center.X+4,r.TopLeft.Y+center.Y+6);
}
else
{
// render seat
renderSeat(ctx,r,seatColors[seatKeyFromPosition(row,col)]);
}
}
}
}
</script>
</head>
<body>
<form id="myForm" onsubmit="renderSeatplan(getSeatInfo(10,16));">
</form>
<div id="output"></div>
<h1>Seatplan</h1>
<canvas id="seatplan" width="640" height="480"></canvas>
</body>
</html>
The code of the Index.html on its own is proven, as it works in the example from user BitTrickler (see link above) I have seen.

Related

When spawning many iterations of a class object, how do I take an object out of the array using a if statement inside of the Class?

I'm a beginner using p5js and I'm trying to work with classes. I'm making a game where you have to find and click a 'wanted man', from a crowd.
So basically, a randomizer picks between 7 different types of 'civilians', and it's supposed to remove one of the types from the 'civilians' that have been spawned. After removing the 'wanted man', I want to add one wanted man so that there is only one 'wanted man'.
So the code spawns a bunch of random 'civilians', then it will delete all 'wanted man' types in the array, and add only one of them. I think there is a better way to do this though.
My basic desire is to have a crowd of 'civilians' that run around, - one of which is a 'wanted man' - and you would have to find and click that 'wanted man' (kind of like a hunting/assassination game).
This is the code for the sketch.js file:
var civilians = [];
var page = 0;
var man1img;
var man2img;
var man3img;
var man4img;
var man5img;
var man6img;
var aliemanimg;
var w;
var h;
var spawnCount = 14;
var wantedMan;
var randCiv;
function preload() {
man1img = loadImage("man1.png");
man2img = loadImage("man2.png");
man3img = loadImage("man3.png");
man4img = loadImage("man4.png");
man5img = loadImage("man5.png");
man6img = loadImage("man6.png");
aliemanimg = loadImage("alieman.png");
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
function setup() {
createCanvas(windowWidth, windowHeight);
imageMode(CENTER);
// wantedMan = round(random(0, 6));
wantedMan = 0;
for (var i = 0; i < spawnCount; i++) {
randCiv = round(random(0, 6));
w = random(windowWidth);
h = random(windowHeight);
civilians.push(new Civilian(w, h, wantedMan, randCiv));
console.log(wantedMan);
if (civilians[i].isWantedMan()) {
//OVER HERE \/
civilians.splice(i, 1);
}
}
civilians.push(new Civilian(w, h, wantedMan, wantedMan));
}
// page setup
// page 1 : main screen (play, settings, and those stuff)
// page 2 : show chosen civilian
// page 3 : playing
// page 4 : lose
// page 5 : options
function draw() {
background(220, 80, 80);
for (var i = civilians.length - 1; i >= 0; i--) {
civilians[i].update();
civilians[i].show(mouseX, mouseY);
if (civilians[i].clickedOn(mouseX, mouseY)) {
// detect if is right person
console.log("clicked on boi");
if (civilians[i].isWantedMan()) {
console.log("HES WANTED");
} else {
console.log("HES NOT WANTED");
}
}
}
text(round(frameRate()), 20, 20);
//show wanted man
var tempImg = man1img;
if (wantedMan == 1) {
tempImg = man2img;
} else if (wantedMan == 2) {
tempImg = man3img;
} else if (wantedMan == 3) {
tempImg = man4img;
}
if (wantedMan == 4) {
tempImg = man5img;
} else if (wantedMan == 5) {
tempImg = man6img;
} else if (wantedMan == 6) {
tempImg = aliemanimg;
}
image(tempImg, 50, 70, 70, 90);
}
This is the code for the class:
class Civilian {
constructor(x, y, wantedMan, type) {
this.x = x;
this.y = y;
this.w = 47;
this.h = 60;
this.t = {
x: x,
y: y,
};
this.size = 47;
this.moveSpeed = 0.01;
this.moveDist = 20;
this.wantedMan = wantedMan;
this.civilian = type
this.civilianImg = man1img
this.wantedMan = wantedMan
}
update() {
//move target to random position
this.t.x = random(this.t.x - this.moveDist, this.t.x + this.moveDist);
this.t.y = random(this.t.y - this.moveDist, this.t.y + this.moveDist);
//edge detect
if (this.t.x < 0) {
this.t.x += 5;
}
if (this.t.x > width) {
this.t.x -= 5;
}
if (this.t.y < 0) {
this.t.y += 5;
}
if (this.t.y > height) {
this.t.y -= 5;
}
//images position follows target but with easing
this.x += (this.t.x - this.x) * this.moveSpeed;
this.y += (this.t.y - this.y) * this.moveSpeed;
}
show(ex, ey) {
var d = dist(ex, ey, this.x, this.y);
if (d > this.size / 2) {
tint(255, 255, 255);
} else {
tint(0, 255, 0);
}
if(this.civilian == 1) {
this.civilianImg = man2img
} else if(this.civilian == 2) {
this.civilianImg = man3img
} else if(this.civilian ==3) {
this.civilianImg = man4img
} if(this.civilian == 4) {
this.civilianImg = man5img
} else if(this.civilian == 5) {
this.civilianImg = man6img
} else if(this.civilian == 6) {
this.civilianImg = aliemanimg
}
image(this.civilianImg, this.x, this.y, 47, 60);
}
clickedOn(ex, ey) {
var d = dist(ex, ey, this.x, this.y);
return d < this.size / 2 && mouseIsPressed;
}
isWantedMan() {
return this.civilian == this.wantedMan;
}
}
However, whenever I add a .splice(i,1) under the 'for' loop in setup function - to remove the 'wanted man', it shows this error:
"TypeError: Cannot read properties of undefined (reading
'isWantedMan') at /sketch.js:41:22".
isWantedMan() is a function in the Civilian Class, that returns true if the current 'civilian' is wanted. The .splice is supposed to remove a object from the array, when it is a 'wanted man'.
I don't know why this happens. When I replace the .splice code with a console.log() code, then there is no error.
Also there were probably a lot of things that I could have done better in the code.

While adding new data on the right side of a canvas, moving entire collection of points to the left

I have a collection of data representing cloud height measurements every minute. As new data arrives, i want to add them on the right side of the canvas, moving the older data to the left. Is it possible to do this without using a specific charting library like canvasjs?
Some additional info to make things a little bit clearer. If the webpage is opened, data of the last 180 minutes are queried by an Ajax call. The data is in json format.
<style>
canvas {
background-color: #ffffff;
}
</style>
<fieldset>
<legend>Wolkenhöhen:</legend>
<div id="theCanvas">
<canvas id="cloudCanvas" width="618" height="510" style="border:1px solid #ffffff;">
</canvas>
</div>
<script>
const blu = '#1c29cc';
const wht = '#000000';
const grn = '#008513';
const ylo = '#e2ff28';
const amb = '#9d4600';
const red = '#9d0313';
const gray = '#8f8481';
const black = '#000000';
var maxY = 510;
var minY = 15;
var minX = 10;
var maxX = 600;
function plotGrit() {
var c = document.getElementById("cloudCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.moveTo(minX+20, minY);
ctx.lineTo(minX+20, maxY-15);
ctx.lineTo(maxX-15, maxY-15);
ctx.strokeStyle = '#c9c9c9';
ctx.stroke();
ctx.closePath();
ctx.font = "10px Arial";
};
function heightLine(hcld,ctxt) {
var arr = {"#9d4600":200,"#e2ff28":300,"#008513":700,"#000000":1500,"#1c29cc":2500};
for (i=0; i<hcld; i+=2000) {
ctxt.beginPath();
ctxt.moveTo(minX+20, (480-480*i/hcld)+minY);
ctxt.lineTo(maxX-15, (480-480*i/hcld)+minY);
ctxt.strokeStyle = gray;
ctxt.stroke();
ctxt.closePath();
ctxt.fillStyle = black;
ctxt.fillText(i, minX-10, (480-480*i/hcld)+minY);
}
for(var key in arr)
{
var hgt = arr[key];
ctxt.beginPath();
ctxt.moveTo(minX+20, (480-480*hgt/hcld)+minY);
ctxt.lineTo(maxX-15, (480-480*hgt/hcld)+minY);
ctxt.strokeStyle = key;
ctxt.stroke();
ctxt.closePath();
}
}
function timeLine(x,ctxt, col) {
ctxt.beginPath();
ctxt.moveTo(x, minY);
ctxt.lineTo(x, maxY-15);
ctxt.lineWidth = 1;
ctxt.strokeStyle = col;
ctxt.stroke();
ctxt.closePath();
}
function cldDot(hgt, x, y ,ctxt) {
// plots a dot representing the measured cloud height
if (hgt >= 2500) {
col = blu;
} else if (hgt >= 1500) {
col = wht;
} else if (hgt >= 700) {
col = grn;
} else if (hgt >= 300) {
col = ylo;
} else if (hgt >= 200) {
col = amb;
} else if ((hgt > 0) && (hgt < 200)) {
col = red;
}
ctxt.fillStyle = col;
ctxt.fillRect(x-3,y-3,3,3);
}
function fetchClouds() {
var multiplier = 1/1000;
var lcld = 400000;
var hcld = 0;
var X = minX+20;
var c = document.getElementById("cloudCanvas");
var ctx = c.getContext("2d");
$.ajax({
type: "Post",
url: "cloudQuery.php?tsteps=180",
success: function(data) {
var obj = $.parseJSON(data);
// Printing all the values from the resulting object
for (var i in obj ) {
cld = obj[i]['cldLyr_Service1'];
cld2 = obj[i]['cldLyr_Service2'];
cld3 = obj[i]['cldLyr_Service3'];
if (cld < lcld && cld != 0) {
lcld = cld;
}
if (cld > hcld) {
hcld = cld;
}
var min = obj[i]['Time'].substring(3,5);
if (min == 00) {
timeLine(X,ctx,black);
ctx.fillStyle = "black";
ctx.fillText(obj[i]['Time'], X-13, maxY-5);
}
if ((min % 10 == 0) && (min != 00)) {
timeLine(X,ctx,gray);
ctx.fillStyle = "black";
ctx.fillText(min, X-7, maxY-5);
}
cldDot(cld, X,(480-480*cld/hcld)+minY,ctx);
if (cld2 > 0) {
cldDot(cld2, X,(480-480*cld2/hcld)+minY,ctx);
}
if (cld3 > 0) {
cldDot(cld3, X,(480-480*cld3/hcld)+minY,ctx);
}
X+=3;
}
heightLine(hcld,ctx);
lcld = 0 + " ft";
ctx.fillStyle = "black";
ctx.fillText(lcld, minX-10, maxY-15);
hcld = hcld + " ft";
ctx.fillText(hcld, minX-10, maxY-490);
}
});
};
fetchClouds();
plotGrit();
$(document).ready(function() {
setInterval(fetchClouds, 1000);
});
</script>
</fieldset>
The result looks like

My canvas in my code is only displaying after my for loop. I am after an animation effect

I am learning javascript OOP and have decided to implement Langstons ant. I am having trouble with the html5 canvas though. When I run this my debugging alerts in Ant.js pop up as expected but only after they have all done does the canvas appear in my browser (chrome). It then looks like the state that it should be at the end of the loop.
Why is this?
Thanks in advance..
Here is my code;
langstonsAnt.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Langstons Ant</title>
<script defer src="antGame.js"></script>
<script src="Ant.js"></script>
<script src="AntWorld.js"></script>
</head>
<body>
<canvas id="antboard" width="700" height="700" style="border: 5px solid black; background-size: 100%;">
Canvas not supported
</canvas>
</body>
</html>
antGame.js
let c = document.getElementById("antboard");
let ctx = c.getContext("2d");
startGame(ctx);
function startGame(ctx)
{
for (let x=0; x<100; x++)
{
for (let y=0; y<100; y++)
{
ctx.fillStyle = "red";
ctx.fillRect(7 * x, 7 * y, 7, 7);
}
}
}
// create antWorld board
let world = new AntWorld(100, ctx);
// create the ant
let ant = new Ant(world.board);
// place the ant on the board
world.setAntPos(ant.getAntX(), ant.getAntY());
// THIS IS THE LOOP I AM REFERRING THAT CALLS THE ALERTS.
for (let i=0; i<16; i++)
{
ant.moveForward();
world.setAntPos(ant.getAntX(),ant.getAntY());
//sleep(100);
}
function sleep(milliseconds) {
let start = new Date().getTime();
for (let i=0; i<1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
Ant.js
class Ant
{
constructor(board)
{
this.board = board;
this.antX = 50;
this.antY = 35;
this.NORTH = 0;
this.EAST = 1;
this.SOUTH = 2;
this.WEST = 3;
this.antDirection = this.NORTH;
}
getAntX()
{
return this.antX;
}
getAntY()
{
return this.antY;
}
moveForward()
{
switch (this.antDirection)
{
case this.NORTH:
// change direction and colour the square based on rules
if (this.board[this.antY][this.antX] === 0) // if sqr is white
{
this.board[this.antY][this.antX] = 1;
alert('About to fillRect');
ctx.fillStyle = "black";
ctx.fillRect(7 * this.antX, 7 * this.antY, 7, 7);
this.antDirection = this.WEST;
} else { // if sqr is black
this.board[this.antY][this.antX] = 0;
alert('About to fillRect');
ctx.fillStyle = "white";
ctx.fillRect(7 * this.antX, 7 * this.antY, 7, 7);
this.antDirection = this.EAST;
}
// move ant forward
this.antY--;
break;
case this.SOUTH:
// then colour the new square based on rules
if (this.board[this.antY][this.antX] === 0)
{
this.board[this.antY][this.antX] = 1;
alert('About to fillRect');
ctx.fillStyle = "black";
ctx.fillRect(7 * this.antX, 7 * this.antY, 7, 7);
this.antDirection = this.EAST;
} else {
this.board[this.antY][this.antX] = 0;
alert('About to fillRect');
ctx.fillStyle = "white";
ctx.fillRect(7 * this.antX, 7 * this.antY, 7, 7);
this.antDirection = this.WEST;
}
// move ant forward
this.antY++;
break;
case this.EAST:
// then colour the new square based on rules
if (this.board[this.antY][this.antX] === 0)
{
this.board[this.antY][this.antX] = 1;
alert('About to fillRect');
ctx.fillStyle = "black";
ctx.fillRect(7 * this.antX, 7 * this.antY, 7, 7);
this.antDirection = this.NORTH;
} else {
this.board[this.antY][this.antX] = 0;
alert('About to fillRect');
ctx.fillStyle = "white";
ctx.fillRect(7 * this.antX, 7 * this.antY, 7, 7);
this.antDirection = this.SOUTH;
}
// move ant forward
this.antX++;
break;
case this.WEST:
// then colour the new square based on rules
if (this.board[this.antY][this.antX] === 0)
{
this.board[this.antY][this.antX] = 1;
alert('About to fillRect');
ctx.fillStyle = "black";
ctx.fillRect(7 * this.antX, 7 * this.antY, 7, 7);
this.antDirection = this.SOUTH;
} else {
this.board[this.antY][this.antX] = 0;
alert('About to fillRect');
ctx.fillStyle = "white";
ctx.fillRect(7 * this.antX, 7 * this.antY, 7, 7);
this.antDirection = this.NORTH;
}
// move ant forward
this.antX--;
break;
}
}
}
AntWorld.js
class AntWorld
{
constructor(size)
{
this.board = Array(size).fill(0).map(()=>Array(size).fill(0));
}
setAntPos(antX, antY)
{
this.board[antY][antX] = 1;
ctx.fillStyle = "black";
ctx.fillRect(7 * antX, 7 * antY, 7, 7);
}
}
What you do (after removing the alerts and uncommenting sleep()) is an busy sleep. That means that in your sleep routine Javascript is kept busy. There's no time to do anything else, like rendering the canvas, because it is looping.
What you need to use is system events to perform the next action. Normally that would be a keypress by the user or the timer.
So, let's recode this bit of code, using the timer:
for (let i=0; i<16; i++)
{
ant.moveForward();
world.setAntPos(ant.getAntX(),ant.getAntY());
sleep(100);
}
With the timer that would become:
function moveTheAnt()
{
ant.moveForward();
world.setAntPos(ant.getAntX(),ant.getAntY());
stepCount++;
if (stepCount > 16) clearInterval(stepTimer);
}
let stepCount = 0;
let stepTimer = setInterval(moveTheAnt, 100);
You can see it in action here: JSFiddle
For more information on the Javascript timer see: https://www.w3schools.com/js/js_timing.asp
For information on events in general see: https://www.w3schools.com/JS/js_events.asp
Both links are just examples, there might be better tutorials out there.
If you want to do animation in JavaScript in the browser you should really be using requestAnimationFrame and structure your code appropriately.
that said, if you just want to hack away you can use async/await in your loop. First we need a function that will wait a while
function sleep(ms = 0) {
return new Promise(resolve => setTimeout(resolve, ms));
}
Then we need to put the loop in an async function and call sleep with the await keyword.
async function loop() {
for (let i=0; i<16; i++)
{
ant.moveForward();
world.setAntPos(ant.getAntX(),ant.getAntY());
await sleep(100); // pause 100 milliseconds
}
}
loop();
Here's an example
function sleep(ms = 0) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function loop() {
for (let i=0; i<16; i++)
{
console.log(i);
await sleep(1000); // pause 1000 milliseconds
}
}
loop();
For more info see: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await

Finding Value in an Indexed array

I have created a function that checks a nested array to see whether an input is valid. For the input to be valid it cannot have the same name twice in the array. Arr[i][0] contains the name of the crop.
function checkList(arr,cropName) {
for (i = 0; i < 32; i++) {
if (arr[i][0] == cropName){
console.log("Name in Array")
return true;
} else {
console.log("Name not in Array")
return false;
}
}
}
for some reason this algorithm doesn't work, but i'm sure it should, any help is appreciated. I have set up a JS fiddle so you can look at it if needed.
https://jsfiddle.net/qdzvr6z1/
You're returning on the first iteration so you're only checking index 0.
Try
function checkList(arr,cropName) {
for (i = 0; i < 32; i++) {
if (arr[i][0] == cropName){
console.log("Name in Array")
return true;
}
}
console.log("Name not in Array")
return false;
}
=== UPDATED ANSWER ===
If this is useful, please vote up my answer. :)
To share some ideas on how you can clean up some code (there would be more to do, but I need to stop to get back to my work), I refactored and enhanced your solution.
Give it a try here Fiddle
html:
<canvas id="myCanvas" width="400" height="200" style="border:1px solid #000000;"></canvas><br>
<input type="color" id="currentColour" value="#ff0000">
<input type="text" id="cropName" placeholder="Please enter a color name"><br>
Mode:<br>
<div style="margin-left: 20px;">
<input type="radio" id="modeAdd" name="mode" value="add" checked>Add</input><br>
<input type="radio" id="modeClear" name="mode" value="clear">Clear</input>
</div>
<div>
<p>Hover over a cell to see the values here:</p>
<div style="margin-left: 20px;">
Name: <input type="text" id="hoverName" /><br>
Colour: <input type="text" id="hoverColour" />
</div>
</div>
script:
const defaultColour = "#ffffff";
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var numColours = 32;
var colours = initialiseArray(numColours, defaultColour);
function initialiseArray(qty, defaultColour) {
var arr = [];
for (i = 0; i < qty; i++) {
arr.push({
name: "",
colour: defaultColour
});
};
return arr
};
//DRAW GRID
function drawGrid() {
var step;
ctx.setTransform(1, 0, 0, 1, 0.5, 0.5);
ctx.beginPath();
//Draw Vertical Lines
for (step = 50; step < 400; step += 50) {
ctx.moveTo(step, 0);
ctx.lineTo(step, 200);
}
//Draw Horizontal Lines
for (step = 50; step < 200; step += 50) {
ctx.moveTo(0, step);
ctx.lineTo(400, step);
//Draw Dividers
ctx.moveTo(200.5, 0);
ctx.lineTo(200.5, 200);
ctx.moveTo(0, 100.5);
ctx.lineTo(400, 100.5);
}
ctx.stroke();
ctx.setTransform(1, 0, 0, 1, 0, 0);
}
//GET MOUSE COORDINATES ON CANVAS
function getMousePos(canvas, evt) {
var rect = c.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
function isColourNameProvided(name) {
if (name) return true
else return false;
}
// looks through an array of colour objects and returns true if the same name AND colour value combo exists
function isDuplicateNameAndColourValue(newColourName, newColourValue) {
return colours.some( c => c.name === newColourName && c.colour === newColourValue);
}
function isUserInputValid(arr, cropName, cropColour) {
if (!isColourNameProvided(cropName)) {
alert("Please set a name for the colour.");
return false;
}
// Check to see if the combination of name and colour value already exists in the palette
if (isDuplicateNameAndColourValue(cropName, cropColour)) {
alert("That combination of NAME and COLOUR VALUE already exists in the palette.");
return false;
}
return true;
}
function getMode() {
var radios = document.getElementsByName("mode");
for (i = 0; i < radios.length; i++) {
if (radios[i].checked) return radios[i].value;
}
return null;
}
function updatePalette(event) {
var cropName;
var cropColour;
var mousePos = getMousePos(c, event);
var xPos = Math.floor(mousePos.x / 50) * 50 + 1;
var yPos = Math.floor(mousePos.y / 50) * 50 + 1;
var width = 49;
var height = 49;
var cellNum = Math.floor(mousePos.y / 50) * 8 + Math.floor(mousePos.x / 50)
switch (getMode().toUpperCase()) {
case "ADD":
cropName = document.getElementById("cropName").value;
cropColour = document.getElementById("currentColour").value;
if (isUserInputValid(colours, cropName, cropColour)) {
updatePaletteCell(cellNum, cropName, cropColour, xPos, yPos, width, height);
}
break;
case "CLEAR":
cropName = "";
cropColour = defaultColour;
updatePaletteCell(cellNum, cropName, cropColour, xPos, yPos, width, height);
break;
default:
alert("Unable to determine the mode.");
break;
}
}
function updatePaletteCell(cellNum, colourName, colourValue, xPos, yPos, width, height) {
// paint the cell
ctx.fillStyle = colourValue;
ctx.fillRect(xPos, yPos, width, height);
// store values for the cell
colours[cellNum].name = colourName;
colours[cellNum].colour = colourValue;
}
function showColourInfo(event) {
var mousePos = getMousePos(c, event);
var cellNum = Math.floor(mousePos.y / 50) * 8 + Math.floor(mousePos.x / 50)
crop = colours[cellNum];
if (crop) {
document.getElementById("hoverName").value = crop.name;
document.getElementById("hoverColour").value = crop.colour;
}
}
c.addEventListener('mousemove', showColourInfo, false);
c.addEventListener('click', updatePalette, false);
drawGrid();
=== ORIGINAL ANSWER ===
The answer Daniel gave is correct, but I think it's better refactored to be like this:
function checkList(arr,cropName) {
var result = arr.some(x => {
return (x[0] === cropName);
});
console.log("Duplicate found = ", result);
return result;
}
Note: This (and the one you posted) will return true in your fiddle right now because you aren't checking before you update the cell, so it will always be found.
Another quick tip:
if (checkInput != false) is commonly done like this: if (checkInput), as this returns true for all values except: false, 0, "", null, undefined, and NaN

JavaScript text wont display

I've been working on a simple matching puzzle game for a little while now. Currently I have been able to have a countdown time and the number of matching tiles displayed as a text and I'm trying to create one for the best time completed (basically how fast the person completed the puzzle). However whenever I try to create it the text never displays.I noticed while writing the code that if I where to place the variable "txt" followed by a "." the autocomplete box will appear with .text as an available option so I would get "txt.text". I do not however get that option when writing the bestTimeTxt variable which is what I am using to display the time. I'm not sure what I have done wrong, here is my code.
<!DOCTYPE html>
<html>
<head>
<title>Recipe: Drawing a square</title>
<script src="easel.js"></script>
<script type="text/javascript">
var canvas;
var stage;
var squareSide = 70;
var squareOutline = 5;
var max_rgb_color_value = 255;
var gray = Graphics.getRGB(20, 20, 20);
var placementArray = [];
var tileClicked;
var timeAllowable;
var totalMatchesPossible;
var matchesFound;
var txt;
var bestTime;
var bestTimeTxt;
var matchesFoundText;
var squares;
function init() {
var rows = 5;
var columns = 6;
var squarePadding = 10;
canvas = document.getElementById('myCanvas');
stage = new Stage(canvas);
var numberOfTiles = rows*columns;
matchesFound = 0;
timeAllowable = 5;
bestTime = 0
txt = new Text(timeAllowable, "30px Monospace", "#000");
txt.textBaseline = "top"; // draw text relative to the top of the em box.
txt.x = 500;
txt.y = 0;
bestTimeTxt = new Text(bestTime, "30px Monospace", "#000");
bestTimeTxt.textBaseLine = "top";
bestTimeTxt.x = 300;
bestTimeTxt.y = 0;
stage.addChild(txt);
stage.addChild(bestTimeTxt);
squares = [];
totalMatchesPossible = numberOfTiles/2;
Ticker.init();
Ticker.addListener(window);
Ticker.setPaused(false);
matchesFoundText = new Text("Pairs Found: "+matchesFound+"/"+totalMatchesPossible, "30px Monospace", "#000");
matchesFoundText.textBaseline = "top"; // draw text relative to the top of the em box.
matchesFoundText.x = 500;
matchesFoundText.y = 40;
stage.addChild(matchesFoundText);
setPlacementArray(numberOfTiles);
for(var i=0;i<numberOfTiles;i++){
var placement = getRandomPlacement(placementArray);
if (i % 2 === 0){
var color = randomColor();
}
var square = drawSquare(gray);
square.color = color;
square.x = (squareSide+squarePadding) * (placement % columns);
square.y = (squareSide+squarePadding) * Math.floor(placement / columns);
squares.push(square);
stage.addChild(square);
square.cache(0, 0, squareSide + squarePadding, squareSide + squarePadding);
square.onPress = handleOnPress;
stage.update();
};
}
function drawSquare(color) {
var shape = new Shape();
var graphics = shape.graphics;
graphics.setStrokeStyle(squareOutline);
graphics.beginStroke(gray);
graphics.beginFill(color);
graphics.rect(squareOutline, squareOutline, squareSide, squareSide);
return shape;
}
function randomColor(){
var color = Math.floor(Math.random()*255);
var color2 = Math.floor(Math.random()*255);
var color3 = Math.floor(Math.random()*255);
return Graphics.getRGB(color, color2, color3)
}
function setPlacementArray(numberOfTiles){
for(var i = 0;i< numberOfTiles;i++){
placementArray.push(i);
}
}
function getRandomPlacement(placementArray){
randomNumber = Math.floor(Math.random()*placementArray.length);
return placementArray.splice(randomNumber, 1)[0];
}
function handleOnPress(event){
var tile = event.target;
tile.graphics.beginFill(tile.color).rect(squareOutline, squareOutline, squareSide, squareSide);
if(!!tileClicked === false || tileClicked === tile){
tileClicked = tile;
tileClicked.updateCache("source-overlay");
}else{
if(tileClicked.color === tile.color && tileClicked !== tile){
tileClicked.visible = false;
tile.visible = false;
matchesFound++;
matchesFoundText.text = "Pairs Found: "+matchesFound+"/"+totalMatchesPossible;
if (matchesFound===totalMatchesPossible){
gameOver(true);
}
}else{
tileClicked.graphics.beginFill(gray).rect(squareOutline, squareOutline, squareSide, squareSide);
}
tileClicked.updateCache("source-overlay");
tile.updateCache("source-overlay");
tileClicked = tile;
}
stage.update();
}
function tick() {
secondsLeft = Math.floor((timeAllowable-Ticker.getTime()/1000));
txt.text = secondsLeft;
bestTimeTxt.text = "test";
if (secondsLeft <= 0){
gameOver(false);
}
stage.update();
}
function gameOver(win){
Ticker.setPaused(true);
for(var i=0;i<squares.length;i++){
squares[i].graphics.beginFill(squares[i].color).rect(5, 5, 70, 70);
squares[i].onPress = null;
if (win === false){
squares[i].uncache();
}
}
var replayParagraph = document.getElementById("replay");
replayParagraph.innerHTML = "<a href='#' onClick='history.go(0);'>Play Again?</a>";
if (win === true){
matchesFoundText.text = "You win!"
}else{
txt.text = secondsLeft + "... Game Over";
}
}
function replay(){
init();
}
</script>
</head>
<body onload="init()">
<header id="header">
<p id="replay"></p>
</header>
<canvas id="myCanvas" width="960" height="400"></canvas>
</body>
</html>
Apparently the issue I was having was that the x and y position of the text was causing it to appear behind everything else.

Categories