Trouble with 'Tic Tac Toe' Classes - class

I am relatively new to JS and have been working on a Tic Tac Toe game as an exercise. I think I am 90% of the way there, but I am having an annoying bug that comes up after the first play through (ie. when a new game is rendered). In this game, each square is given a class ('x' or 'o') when the corresponding player clicks on it. The game logic checks if that player has any of the game winning combinations, and if they do resets the game (removing the 'x' and 'o' tile classes). This seems to work, but upon subsequent clicking in the next round, some tiles are given BOTH 'x' and 'o' classes, which basically breaks the game. For example, the game can be won with a line of 'x', 'x' and 'o'.
EDIT 1: Okay, so I think the problem is that newGame() is running twice. Still trying to figure out a solution.
I've been searching every for an answer to this, but to no avail! I've included my code below. Thanks!!
$(document).ready(function() {
var xTurn = true;
var xScore = 0;
var oScore = 0;
var count = 0;
newGame();
function newGame() {
$("td").removeClass();
$("td").empty();
count = 0;
xTurn = true;
render();
game();
}
function render() {
$("#xScore").text("x Score: " + xScore);
$("#oScore").text("o Score: " + oScore);
}
function game() {
$("td").on("click", function () {
var self = $(this);
if (xTurn) {
self.text("X");
self.addClass("x");
}
else {
$(this).text("O");
self.addClass("o");
}
xTurn = !xTurn;
$(this).off("click");
count ++;
scoreEval();
});
function scoreEval() {
if (
$("#one").hasClass('x') && $("#two").hasClass('x') && $("#three").hasClass('x') ||
$("#four").hasClass('x') && $("#five").hasClass('x') && $("#six").hasClass('x') ||
$("#seven").hasClass('x') && $("#eight").hasClass('x') && $("#nine").hasClass('x') ||
$("#one").hasClass('x') && $("#four").hasClass('x') && $("#seven").hasClass('x') ||
$("#two").hasClass('x') && $("#five").hasClass('x') && $("#eight").hasClass('x') ||
$("#three").hasClass('x') && $("#six").hasClass('x') && $("#nine").hasClass('x') ||
$("#one").hasClass('x') && $("#five").hasClass('x') && $("#nine").hasClass('x') ||
$("#three").hasClass('x') && $("#five").hasClass('x') && $("#seven").hasClass('x')
) {
xScore ++;
alert("Player X has won the game!");
newGame();
}
else if (
$("#one").hasClass('o') && $("#two").hasClass('o') && $("#three").hasClass('o') ||
$("#four").hasClass('o') && $("#five").hasClass('o') && $("#six").hasClass('o') ||
$("#seven").hasClass('o') && $("#eight").hasClass('o') && $("#nine").hasClass('o') ||
$("#one").hasClass('o') && $("#four").hasClass('o') && $("#seven").hasClass('o') ||
$("#two").hasClass('o') && $("#five").hasClass('o') && $("#eight").hasClass('o') ||
$("#three").hasClass('o') && $("#six").hasClass('o') && $("#nine").hasClass('o') ||
$("#one").hasClass('o') && $("#five").hasClass('o') && $("#nine").hasClass('o') ||
$("#three").hasClass('o') && $("#five").hasClass('o') && $("#seven").hasClass('o')
) {
oScore ++;
alert("Player O has won the game!");
newGame();
}
else if (count === 9) {
alert("Draw!");
newGame();
}
}
}
});
table, td {
border: 1px solid black;
font-size: 50px;
text-align: center;
}
td {
height: 100px;
width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<html>
<head>
<title>Tic Tac Toe</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<div id="score">
<p>Score</p>
<p id="xScore"></p>
<p id="oScore"></p>
</div>
<table>
<tr>
<td id="one"></td>
<td id="two"></td>
<td id="three"></td>
</tr>
<tr>
<td id="four"></td>
<td id="five"></td>
<td id="six"></td>
</tr>
<tr>
<td id="seven"></td>
<td id="eight"></td>
<td id="nine"></td>
</tr>
</table>
<script src="script.js"></script>
</body>
</html>

You should check in onClick event if there is assigned X or O, before doing any action. I reproduced an error by clicking on box that already has X/O in it.

Related

Open popup after flyTo in Leaflet?

I have a Leaflet-map with a layer containing markers with popups using bindPopup. I written this function that flies to the next marker onclick:
const makeFlyTo = () => {
const button = document.getElementById("next");
L.DomEvent.on(button, "click", function(e) {
if (currentView === data.length) {
currentView = 0;
}
map.flyTo(
[data[currentView].lat, data[currentView].lng],
{ zoom },
{
animate: true,
duration: 3
}
);
currentView++;
});
};
I would be nice if the popup opened up on "arrival". Any idea how this can be done?
We have to open marker first and they use FlyTo.
marker.openPopup();
map.flyTo([value['lat'], value['lng']], 15);
As mentioned in the comments, If we use flyTo and then open Popup then most of the times the view adjustment made by popup in map is incorrect.
map.panTo([value['lat'], value['lng']], 15).on('zoomend', () => { setTimeout(()=>marker.openPopup(), 3000) })
OR
map.panTo([value['lat'], value['lng']], 15).on('zoomend', () => marker.openPopup())
Example -
var map = L.map("map").setView([46.76336, -71.32453], 16);
var OpenStreetMap_Mapnik = L.tileLayer(
"http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
{
maxZoom: 19,
attribution:
'© OpenStreetMap'
}
).addTo(map);
function addRowTable(marker, code, coords) {
var tr = document.createElement("tr");
var td = document.createElement("td");
td.textContent = code;
tr.appendChild(td);
tr.onclick = () => {
marker.openPopup();
map.flyTo([value['lat'], value['lng']], 15);
};
document.getElementById("t_points").appendChild(tr);
}
function addMarker(code, lat, lng) {
var marker = L.marker([lat, lng]);
marker.title = code;
marker.bindPopup(code);
marker.addTo(map);
addRowTable(marker, code, [lat, lng]);
}
$(document).ready(function () {
var points = [
["M02KM262", 46.76336, -71.32453],
["M10KM052", 46.76186, -71.32247],
["83KM081", 46.76489, -71.32664],
["83KM082", 46.76672, -71.32919]
];
for (var i = 0; i < points.length; i++) {
addMarker(points[i][0], points[i][1], points[i][2]);
}
});
html, body, .full, #map{
margin: 0;
padding:0;
height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>
<script src="https://unpkg.com/leaflet#1.0.3/dist/leaflet.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://unpkg.com/leaflet#1.0.3/dist/leaflet.css" rel="stylesheet"/>
<div class="row full">
<div class="col col-sm-3 full" style="overflow: auto;">
<h3 >List</h3>
<table class="table table-bordered">
<thead>
<tr>
<th>Codes</th>
</tr>
</thead>
<tbody id="t_points"></tbody>
</table>
</div>
<div id="map" class="col col-sm-9 full"></div>
</div>

How to change ion-range value base on ion-input?

I'm trying to make ion-range with input. First, when I using ion-range it getting the right value(this.selectedNominal) but when I'm trying using ion-input to change the value it doesn't changing. It still using first ion-range value.
HTML
<ion-list-header>
Nominals
</ion-list-header>
<ion-item *ngFor="let b of listNom2">
<ion-range min="{{b.min}}" max="{{b.max}}" step="{{b.step}}" [(ngModel)]="nominal2" (ngModelChange)="optionsNominal(nominal2)" color="secondary">
<ion-label range-left style="font-weight: bolder;">{{ b.min | number:0 }}</ion-label>
<ion-label range-right style="font-weight: bolder;">{{ b.max | number:0 }}</ion-label>
</ion-range>
</ion-item>
<div style="text-align: center;margin-left:25%;margin-right:25%;padding-bottom:10px;">
<ion-input maxlength="8" type="tel" [pattern]="[0-9]" (ionChange)="setValue2(nominal2)" style="border:1px solid #FF9900;border-radius:5px;" [(ngModel)]="nominal2" (ionChange)="optionsNominal(nominal2)">Rp.{{ nominal | number:0 }}</ion-input>
</div>
TS
setValue2(nominal2) {
if(nominal2 == null || nominal2 == undefined || nominal2 == '') {
this.nominal2 = 0
} else {
this.nominal2 = parseInt(nominal2);
}
if (this.nominal2 > 50000000) {
this.nominal2 = 50000000;
} else if (this.nominal2 < 3000000) {
this.nominal2 = 3000000;
}
}
optionsNominal(value: any) {
if (value == NaN || value == null || value == undefined || value == '') {
this.selectedNominal = 0;
} else {
this.selectedNominal = value;
}
}

Angular UI Datepicker. Enable only 5 days from today excluding weekends

I am using Angular UI Bootstrap datepicker directive in my project. I have this specific need like I need to enable only 5 days from current day. In case of weekend, I need to disable them and enable the remaining days. for eg, If current day in Friday, I need to enable fri, mon, tue, web, thurs. I am using dateDisabled property to achieve this. Problem is all past month dates are also getting enabled. Also I think the solution I came up is not elegant. Below is my markup and code. Kindly help me. Thank you in advance.
<input show-weeks="false" ng-click="vm.openDate()" name="quotedate" type="text" class="form-control" ng-model-options="{timezone:'UTC'}" uib-datepicker-popup="dd/MM/yyyy" ng-model="vm.quote.date" is-open="vm.quotedate.opened" datepicker-options="vm.dateOptions" required close-text="Close" readonly="true"/>
vm.dateOptions = {
dateDisabled: disabled,
minDate: today
};
function disabled(data) {
var date = data.date,
mode = data.mode;
if (today.getDay() === 0 || today.getDay() === 6) {
return mode === 'day' && (date.getDay() === 0 || date.getDay() === 6 || date.getDate() > today.getDate() + 5 );
}else if (today.getDay() === 1) {
return mode === 'day' && (date.getDay() === 0 || date.getDay() === 6 || date.getDate() > today.getDate() + 4 );
}else {
return mode === 'day' && (date.getDay() === 0 || date.getDay() === 6 || date.getDate() > today.getDate() + 6 );
}
}
What you are looking for are the min-date, max-date, and date-disabled attributes, as described in the docs. The date-disabled function in this example is pulled directly from the docs, and in order to confine the available date range, simply set the min-date attribute to the current datetime:
vm.dt = new Date();
vm.minDate = angular.copy(vm.dt);
...and the max-date to five days from now:
var fiveDaysFromNow = angular.copy(vm.dt);
fiveDaysFromNow.setDate(fiveDaysFromNow.getDate() + 5);
vm.maxDate = fiveDaysFromNow;
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('DatepickerDemoCtrl', function ($scope) {
var vm = this;
function today() {
vm.dt = new Date();
}
today();
vm.opened = false;
vm.openDatePopup = function() {
vm.opened = true;
};
// Disable weekend selection
vm.disabled = function(date, mode) {
return mode === 'day' && (date.getDay() === 0 || date.getDay() === 6);
};
vm.minDate = angular.copy(vm.dt);
var fiveWeekdaysFromNow = angular.copy(vm.dt);
fiveWeekdaysFromNow.setDate(fiveWeekdaysFromNow.getDate() + 7);
vm.maxDate = fiveWeekdaysFromNow;
vm.dateOptions = {
formatYear: 'yy',
startingDay: 0
};
vm.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
vm.format = vm.formats[0];
});
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-animate.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-1.1.0.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<style>
.full button span {
background-color: limegreen;
border-radius: 32px;
color: black;
}
.partially button span {
background-color: orange;
border-radius: 32px;
color: black;
}
</style>
<div ng-controller="DatepickerDemoCtrl as demo">
<div class="row">
<div class="col-xs-8 col-xs-offset-2">
<p class="input-group">
<input type="text"
class="form-control"
uib-datepicker-popup="{{demo.format}}"
ng-model="demo.dt"
show-weeks="false"
is-open="demo.opened"
min-date="demo.minDate"
max-date="demo.maxDate"
datepicker-options="demo.dateOptions"
date-disabled="demo.disabled(date, mode)"
ng-required="true"
close-text="Close"/>
<span class="input-group-btn">
<button type="button"
class="btn btn-default"
ng-click="demo.openDatePopup()">
<i class="glyphicon glyphicon-calendar"></i>
</button>
</span>
</p>
</div>
</div>
</div>
</body>
</html>
Hope this helps!

SQL Injection Indication and Solution

Hi I am developing a website starting from the template Metronic (HTML Template Boiler) that uses Bootstrap.
People say that this code have risk SQL injection.
Can you tell me where is code section bad and how can I fix it?
<div class="container main">
<div class="main_pad">
<?php
if(isset($_GET['ID'])) {
$arrayResult = array();
$query = $dbConnect->query("
SELECT
designers.ID AS ID_designer,
designers.nome AS nome_designer,
designers.immagine AS immagine_designer,
designers.testo_IT AS testo_IT_designer,
designers.testo_EN AS testo_EN_designer,
designers.website AS website_designer,
designers.ID_linea AS ID_linea_designer
FROM
designers
WHERE
ID = '" . $_GET['ID'] . "'
");
$result = $dbConnect->extractObject($query);
if(count($result)>0) {
for($i=0;$i<count($result);$i++) {
$fileParts = pathinfo($result[$i]->immagine_designer);
$basename = substr($fileParts['filename'], 0, -4);
$arrayResult = array(
$result[$i]->ID_designer, // 0
utf8_encode($result[$i]->nome_designer), // 1
$basename . '_640.' . $fileParts['extension'], // 2
utf8_encode($result[$i]->testo_IT_designer), // 3
utf8_encode($result[$i]->testo_EN_designer), // 4
$result[$i]->website_designer, // 5
$result[$i]->ID_linea_designer // 6
);
}
}
?>
<div class="col-lg-6 designer">
<img src="images/left-arrow.png">
<h1><?php echo $arrayResult[1]; ?></h1>
<ul class="top-nav nav-tabs" id="specs" role="tablist">
<li class="active">
<?php echo $_SESSION['langPref']=='ENG' ? "BIO" : 'BIOGRAFIA'; ?>
</li>
<li>
<?php echo $_SESSION['langPref']=='ENG' ? "PRODUCTS" : 'PRODOTTI'; ?>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="bio">
<div class="row">
<div class="col-lg-12">
<p style="margin-top: 20px;">
<?php
switch($_SESSION['langPref']){
default :
case 'ENG' :
echo $arrayResult[4];
break;
case 'IT' :
echo $arrayResult[3];
break;
}
?>
</p>
</div>
</div>
</div>
<div class="tab-pane" id="products">
<div class="row">
<div class="col-lg-12">
<?php
$arrayLinesList = array();
foreach(explode(',', $arrayResult[6]) as $lines => $line) {
$arrayLinesList[] = '"' . $line . '",';
}
$query = $dbConnect->query("
SELECT
*
FROM
prodotti
WHERE
prodotti.ID_linea IN (" . substr(implode('', $arrayLinesList), 0, -1) . ")
");
$result = $dbConnect->extractObject($query);
if(count($result)>0) {
echo '<ul style="margin-top: 20px;">';
for($i=0;$i<count($result);$i++) {
$co = '';
if($result[$i]->ID == 58){
$co = '(Claudio Dondoli)';
}elseif($result[$i]->ID == 53 && $_GET['ID'] == 19 || $result[$i]->ID == 40 && $_GET['ID'] == 19 || $result[$i]->ID == 41 && $_GET['ID'] == 19 || $result[$i]->ID == 62 && $_GET['ID'] == 19 || $result[$i]->ID == 63 && $_GET['ID'] == 19) {
$co = '(with Gianfranco Gualtierotti)';
}elseif($result[$i]->ID == 53 && $_GET['ID'] == 7 || $result[$i]->ID == 40 && $_GET['ID'] == 7 || $result[$i]->ID == 41 && $_GET['ID'] == 7 || $result[$i]->ID == 62 && $_GET['ID'] == 7 || $result[$i]->ID == 63 && $_GET['ID'] == 7) {
$co = '(with Giancarlo Vegni)';
}elseif($result[$i]->ID == 26 && $_GET['ID'] == 10 || $result[$i]->ID == 27 && $_GET['ID'] == 10 || $result[$i]->ID == 28 && $_GET['ID'] == 10 || $result[$i]->ID == 29 && $_GET['ID'] == 10 || $result[$i]->ID == 61 && $_GET['ID'] == 10) {
$co = '(with Patricia Urquiola)';
}elseif($result[$i]->ID == 26 && $_GET['ID'] == 18 || $result[$i]->ID == 27 && $_GET['ID'] == 18 || $result[$i]->ID == 28 && $_GET['ID'] == 18 || $result[$i]->ID == 29 && $_GET['ID'] == 18 || $result[$i]->ID == 61 && $_GET['ID'] == 18) {
$co = '(with Sung Sook Kim)';
}
echo '<li>' . utf8_encode($arrayLines[$result[$i]->ID_linea][0]) .'&nbsp'. $result[$i]->nome .' &nbsp' . ($co) .'</li>';
}
echo '</ul>';
} else {
echo '<p style="margin-top: 20px;">This designer has no products listed here!</p>';
}
?>
</div>
</div>
</div>
</div>
</div><!-- /.left_cont -->
<div class="col-lg-6 right_cont">
<img src="admin/assets/admin/layout/img/designers/<?php echo $arrayResult[2]; ?>" class="img-responsive" />
</div><!-- /.right_cont -->
<?php
}
?>
possible injection in
WHERE ID = '" . $_GET['ID'] . "'
for example if $_GET['ID'] = "' or 1 = 1"
solution: use parametrized queries.
One problem (not read all the code) is building sql statements directly from user input (for example get or post data)
In your code you have
WHERE ID = '" . $_GET['ID'] . "'
You should use prepared statements - read How can I prevent SQL injection in PHP?
if ur using PDO then be sure to use:
WHERE `id`=:id
and then use like:
$stmnt = $dbConnect->prepare($sql);
$stmnt->execute(Array(":id"=>$_GET['id']));
also if you want to protect from higher levels search up the magic quotes liberary, that should help you a bit ;)

How to render jqPlot chart in asp.net MVC

I am trying to render a jqPlot bar chart using asp.net MVC. Not sure how to build an array on the client side using the data returned from a controller.
I am trying to which is similar to this, http://jsfiddle.net/du8GZ/
#foreach (var d in Model.SampleChart)
{
// What to write here?
}
public class SampleChart
{
public int Count { get; set; }
public string Name { get; set; }
}
public ActionResult BarIn()
{
List<SampleChart> data = new List<SampleChart>();
SampleChart bar;
Random r = new Random();
for (int i = 0; i < 10; i++)
{
bar = new SampleChart();
bar.Count = i;
bar.Name = "Sample " + i.ToString();
data.Add(bar);
}
return View(data);
}
<link class="include" rel="stylesheet" type="text/css" href="#Url.Content("~/scripts/jqplot/css/jquery.jqplot.min.css")" />
<!--[if lt IE 9]><script language="javascript" type="text/javascript" src="#Url.Content("~/scripts/jqplot/excanvas.min.js")"></script><![endif]-->
<script type="text/javascript" src="#Url.Content("~/scripts/jqPlot/jquery.jqplot.min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/scripts/jqplot/jqplot.categoryAxisRenderer.min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/scripts/jqPlot/jqplot.barRenderer.min.js")"></script>
<div class="example-content">
<!-- Example scripts go here -->
<style type="text/css">
.jqplot-target
{
margin: 30px;
}
.tooltipCss
{
position: absolute;
background-color: #b2b1ac;
color: White;
z-index: 200;
padding: 5px;
border-radius: 5px;
display: none;
}
</style>
<div id="chart2" class="plot" ></div>
</div>
<script type="text/javascript">
$(document).ready(function () {
var data = new Array();
var series = new Array();
#foreach (var d in Model.SampleChart)
{
}
plot2 = $.jqplot('chart2', data, {
seriesDefaults: {
renderer: $.jqplot.BarRenderer,
rendererOptions: {
barDirection: 'horizontal',
barPadding: 10,
barMargin: 15
}
},
series: series,
axes: {
yaxis: {
renderer: $.jqplot.CategoryAxisRenderer
}
}
});
$('#chart2').bind('jqplotDataMouseOver',
function (ev, seriesIndex, pointIndex, data) {
//$('#info2').html('series "' + series[seriesIndex].label + '" point "' + (pointIndex + 5) + '"<br /> value "' + data[1] + '"');
//$('#info2').css({ "left": ev.pageX + 3, "top": ev.pageY })
$('#info2').show();
}
);
$('#chart2').bind('jqplotDataUnhighlight',
function (ev) {
$('#info2').hide();
}
);
});
</script>
<div id="info2" class="tooltipCss"></div>
The array on your client side is actually represented in JSON so all you have to do is create a view model that will hold a representation of your array and dump it in a hidden field as JSON ... like this:
#Html.Hidden("BarGraphData",Json.Encode(Model.BarGraphData))
and then use jQuery to send the data to jqPlot like that:
var columnChartData = $.parseJSON($('#BarGraphData').val());
var plot2 = $.jqplot('chart1', columnChartData ,{....