I have a timetable on my website. The user can select multiple times. The selected time is inserted into the database and the button turns from green to red, so the user know it's disabled.
I want to do this with only a reload of div.
It does work but it work only once, when pushing the button for the second time the div doesn't refresh / reload.
Update database / refresh;
$('.updateTime').click(function(){
var getUrlParameter = function getUrlParameter(sParam) {
var sPageURL = window.location.search.substring(1),
sURLVariables = sPageURL.split('&'),
sParameterName,
i;
for (i = 0; i < sURLVariables.length; i++) {
sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] === sParam) {
return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
}
}
};
var uniqueId = $(this).attr('id');
var sdate = getUrlParameter('date');
$.ajax({
url: './ajax/reservation_insert_times.php',
type: 'POST',
data: {
uniqueId :uniqueId, sdate :sdate
},
success: function(mydiv){
$("#result").load(location.href+ ' #mydiv');
}
});
});
The code for generating the times
<div class="row" id="result">
<?
$result = array();
$query = $db->query("SELECT * FROM reservation_times WHERE datum = '" . db_escape($_GET['date']) . "' ");
while($row = mysqli_fetch_array($query)) {
$result[] = $row['time'];
}
?>
<?
$timestamp = strtotime(date("Y-m-d")." 12:00");
for ($i=0;$i<=32;$i++) {
$time = date('H:i', $timestamp);
$time .= ' UUR';
if (in_array($time, $result)) {
$color = "background-color:red !important";
}
else $color = "";
$timestamp += 15 * 60;
if (isset($checked) && $checked !='') { $color = 'background-color: red;';}?>
<div class="col-xs-4 col-md-3 col-lg-2" id="mydiv">
<button type="button" id="<?=$time;?>" class="btn btn-block btn-success btn-sm text-center" style="padding:10px; margin-bottom:10px; <?=$color;?>" onclick="" <? if (isset($checked) && $checked !='') { echo 'disabled';}?>>
<?=$time;?>
</button>
</div>
<? } ?>
</div>
The code for the reservation_availablity.php call:
$query = $db->query("SELECT * FROM reservation_times WHERE time = '".$uniqueId."'");
if(mysqli_num_rows($query) == 1) {
$remove = $db->query("DELETE FROM reservation_times WHERE time = '".$uniqueId."'");
} else {
if (isset($uniqueId) && $uniqueId !='') :
$sql = $db->query("INSERT INTO reservation_times (time, datum)
VALUES ('".$uniqueId."', '".$newDate."')");
endif;
}
Change you success method of your ajax:
$.ajax({
url: './ajax/reservation_insert_times.php',
type: 'POST',
data: {
uniqueId :uniqueId, sdate :sdate
},
success: function(mydiv){
$("#result").html(mydiv);
}
});
You are sending an ajax to get new content but then in success method instead of loading new content received as ajax response you are again loading the content of the same div. That's why it is working for the first time but will remain unchanged next time onwards.
//Wrong
$("#result").load(location.href+ ' #mydiv');
// Correct
$("#result").html(mydiv);
So, now whenever this ajax send to the server, it will update the content of div#result. And to allow user to manually refresh the content of this div as and when desired then you will have to call this ajax upon click of a button labled as Refresh Timetable.
I have a code for showing list from database and a loadmore button. After all records list is displayed and click on loadmore button show empty places.
How to hide loadmore button once all records displayed?
index.php file:
<?php $chinp=$_GET['schinp'];?>
<div id="schts"></div>
<button id="btnsch">load more</button>
<script>
$(document).ready(function() {
var chinp="<?php echo $chinp;?>";
var srchco = 1;
var offsrch = 0;
$("#btnsch").click(function() {
$.ajax({
method: "POST",
url: "search.php",
data: { srchcoun: srchco, offsrch: offsrch ,chinp:chinp}
})
.done(function(msg) {
$("#schts").append(msg);
});
offsrch = offsrch + srchco;
});
$("button").trigger("click");
});
</script>
search.php :
$srchcoun=$_POST['srchcoun'];
$offsrch=$_POST['offsrch'];
$chinp=$_POST['chinp'];
$schql="SELECT id, name, lastname FROM t_users WHERE name LIKE '$chinp' ORDER BY name ASC limit $offsrch, $srchcoun";
$rsch=mysqli_query($conn,$schql);
while ($rch=mysqli_fetch_assoc($rsch)){
$scid=$rch['id'];$snm=$rch['name'];$slnm=$rch['lastname'];?>
<div class="alsu">
<img class="sask" src="pic/<?php echo $scid;?>.png" alt="">
<span class="snm">Name : <?php echo $snm." ".$slnm;?></span>
</div>
<?php }?>
</div>
Thanks.
Here is code to hide load more button as per your code.
Replace this code in your first file.
<script type="text/javascript">
$(document).ready(function() {
var chinp="<?php echo $chinp;?>";
var srchco = 2;
var offsrch = 0;
var page_num = 0;
$("#btnsch").click(function() {
$.ajax({
method: "POST",
url: "search.php",
data: { srchcoun: srchco, offsrch: offsrch ,chinp:chinp, page_num : page_num}
})
.done(function(msg) {
if(msg == 'noMoreData'){
$("#btnsch").hide();
} else {
$("#schts").append(msg);
}
});
page_num = page_num + 1;
offsrch = offsrch + srchco;
});
$("#btnsch").trigger("click");
});
</script>
Now add this code in your search file.
<?php
$srchcoun=$_POST['srchcoun'];
$offsrch=$_POST['offsrch'];
$chinp=$_POST['chinp'];
$page_num=$_POST['page_num'];
$total_records = 0;
$totalschql="SELECT id FROM t_users WHERE name LIKE 'krishna' ORDER BY name ASC";
if ($result=mysqli_query($conn,$totalschql))
{
$total_records=mysqli_num_rows($result);
}
$last_records_count = ($page_num) * $srchcoun;
if($last_records_count >= $total_records) {
echo 'noMoreData';exit();
} else {
$schql="SELECT id, name, lastname FROM t_users WHERE name LIKE '$chinp' ORDER BY name ASC limit $offsrch, $srchcoun";;
$rsch=mysqli_query($conn,$schql);
while ($rch=mysqli_fetch_assoc($rsch)){
$scid=$rch['id'];$snm=$rch['name'];$slnm=$rch['lastname'];
?>
<div class="alsu">
<img class="sask" src="pic/<?php echo $scid;?>.png" alt="">
<span class="snm">Name : <?php echo $snm." ".$slnm;?></span>
</div>
<?php }?>
</div>
<?php
}
?>
Try this and let me know if you have any issue.
Simply use $('#myButtonId').hide(); in ajax part after you load the entire data from database.
function get_rain_data_list(is_load_more=0){
if(is_load_more!=0){//if is_load_more is not 0 then get offset data from btnlod attr
offset = $('#btn_load_more_rain').attr("data-offset");
}else{ //set offset =0 when is_load_more is 0
offset = 0;
}
var id = $('#id').val();
var countShow = 0;
if(fromDate!=''){
countShow = 1;
}
$.ajax({
url: base_url+"rain_data_list_ajax",
type: "POST",
data:{offset:offset,propertyId:propertyId,fromDate:fromDate,toData:toData},
dataType: "JSON",
beforeSend: function() {
show_loader();
},
success: function(data){
hide_loader();
// console.log(data);
$('.proprty_load_more_btn').remove();//remove load more button
if(offset==0){ //clear div when offset 0
$("#append_rain_list").html('');
}
if(data.no_record==0){//show data in div when no previous record
$("#append_rain_list").html(data.html_rain);
$("#add_count").html('');
if(countShow){
//$("#add_count").html(data.count+data.record);
}
}else{
//append data when already record show in view
$("#append_rain_list").append(data.html_rain);
$("#append_load_btn").append(data.btn_html);
$("#add_count").html('');
if(countShow){
$("#add_count").html(data.count+data.record);
}
}
},
});
}
<div id="append_rain_list"></div>
<div id="add_count"></div>
<?php
function rain_data_list_ajax(){
$limit = 6;
$is_next = 0;
//get and set offset
$offset = $this->input->post('offset');
$data['property_id'] = decoding($this->input->post('propertyId'));
$fDate = sanitize_input_text($this->input->post('fromDate'));
$tDate = sanitize_input_text($this->input->post('toData'));
$new_offset = $limit+$offset; //pr($data);
//set where
$where = array('property_id'=>$data['property_id']);
//set select field to get
$data['limit'] = $limit;
$data['offset'] = $offset;
//get count of records
$dataView['total_count'] = $this->Property_model->get_rain_count($data);
//get records
$dataView['rain_list'] = $this->Property_model->get_rain_list($data);
///lq();
//check for load more btn
//pr($dataView);
if($dataView['total_count']>$new_offset){
$is_next =1;
}
$btn_html = '';
if($is_next){
//if is next =1 set load more button in btn_html
$id = "btn_load_more_rain";
$btn_html = '<div class="col-sm-12 text-center pt-20 proprty_load_more_btn"><button class="login-btn load load_more_btn" id = "'.$id.'" data-offset ="'.$new_offset.'" data-isNext ="'.$is_next.'" >'.lang('load_more').'</button></div>';
}
//load view with data
$html_rain = $this->load->view('test1',$dataView,true);
$response = array('status'=>1,'html_rain'=>$html_rain,'btn_html'=>$btn_html,'count'=>$dataView['total_count'],'record'=>lang('recod_found'));
//flag for no record
$no_record=1;
if(empty($dataView['rain_list'])){
$no_record = 0;
}
$response['no_record'] = $no_record;
echo json_encode($response);die;
}
?>
I am working on dynamic j query data table where i want to show data from 3 tables.
It should be expandable.I am done to achieve with 1 table. but after joins another 2 tables its not working.
I am attaching my tables format and all pictures how should be my data look.
I have total 4 tables. employee_master,uk_slip,germany_slip,poland_slip.
each user have his pay_slips for each country for each month.
For eg. XYZ is employee.
he will get his 3 salary_slips for 2018-FEBRUARY.I want to show one datatable where first user will see his name then on expand datatable he will get in below format his all slips.
My current code is is showing only data from uk_slip. after UK another tables data should be display.
My model:
public function get_all_payslips()
{
$empid = $this->session->userdata('EMPLOYEE_ID');
$orgid = $this->session->userdata('CURRENT_ORG_ID');
$where = "EMPLOYEE_ID ='".$empid."' ";
$response = array();
$queryString = "SELECT
em.EMPLOYEE_ID,
em.EMPLOYEE_NAME
FROM
uk_slip assd,
employee_master em
WHERE
em.".$where."
GROUP BY em.EMPLOYEE_ID
order by em.EMPLOYEE_NAME asc";
$query = $this->db->query($queryString);
foreach ($query->result() as $data)
{
$result = array();
$result['EMPLOYEE_NAME'] = $data-> EMPLOYEE_NAME;
$queryString = "SELECT
mo.months,
MONTH((assd.pay_period)) as monthss,
YEAR((assd.pay_period)) as PAY_YEAR,
GROUP_CONCAT(DISTINCT(assd.id)) as action,
CONCAT(assd.ORG_ID,',',germany.ORG_ID,',',poland.ORG_ID) as org
FROM
uk_new_salary_slip assd,
employee_master em,
months mo,
germany_slip germany,
poland_slip poland
WHERE
assd.emp_id = ". $data->EMPLOYEE_ID ."
AND mo.id = MONTH((assd.pay_period))
GROUP BY monthss,PAY_YEAR
order by PAY_YEAR desc";
$query1 = $this->db->query($queryString);
$children = array();
foreach ($query1->result() as $data1)
{
$yearArray = array();
$yearArray['month'] = $data1->months;
$yearArray['year'] = $data1->PAY_YEAR;
$yearArray['org'] = $data1->org;
$yearArray['action'] = $data1->action;
array_push($children, $yearArray);
}
$result['children'] = $children;
array_push($response, $result);
}
return $response;
}
My View with jquery datatable:
$(document).ready(function()
{
var table = null;
$.ajax({
url:"<?php echo base_url('responsible/get_all_payslips'); ?>",
datatype:'json',
success: function(response)
{
var response1 = $.parseJSON(response);
console.log(JSON.stringify(response1['pay_slips']));
var data = response1['pay_slips'];
table = $('.datatables').DataTable({
columns : [
{
className : 'details-control',
defaultContent : '',
data : null,
orderable : false
},
{data : 'EMPLOYEE_NAME'},
],
data : data,
pagingType : 'full_numbers',
});
}
});
function format(data)
{
return '<div class="details-container">'+
'<table class="details-table table-bordered">'+
'<thead>'+
'<tr>'+
'<th>Year</th>'+
'<th>Month</th>'+
'<th>PDF</th>'+
'</tr>'+
'</thead>'+
'<tbody>'+
'<tr>'+
'<td>'+data.PAY_YEAR+'</td>'+
'<td>'+data.monthss+'</td>'+
'<td>'+'<a class="btn btn-success" href="data.action">'+data.action+'</a>'+'</td>'+
'</tr>'+
'<tr>'+
'<td>'+data.PAY_YEAR+'</td>'+
'<td>'+data.monthss+'</td>'+
'<td>'+'<a class="btn btn-success" href="data.action">'+data.action+'</a>'+'</td>'+
'</tr>'+
+'</tbody>'+
'</table>'+
'</div>';
};
$('.datatables tbody').on('click', 'td.details-control', function ()
{
var tr = $(this).closest('tr');
var row = table.row( tr );
console.log(row.data()['children']);
var childrenArray = row.data()['children'];
var check = '<div class="details-container">'+
'<table class="details-table table-bordered">'+
'<thead>'+
'<tr>'+
'<th>Year</th>'+
'<th>Month</th>'+
'<th>PDF</th>'+
'</tr>'+
'</thead>'+
'<tbody>';
for(var i=0;i<childrenArray.length;i++)
{
check +='<tr>'+
'<td>'+childrenArray[i].year+'</td>'+
'<td>'+childrenArray[i].month+'</td>';
var orgid = childrenArray[i].org.split(",");
var action = childrenArray[i].action.split(",");
var obj = {};
for (var k = 0; k < orgid.length; k++)
{
obj[orgid[k]] = action[k];
}
var arrayData = sortObject(action);
check +='<td>';
for(var j=0;j<arrayData.length;j++)
{
var country = "";
var color = "";
if(arrayData[j].key=="40")
{
country = "1";
color = "INDIANRED";
}
else if(arrayData[j].key=="41")
{
country = "2";
color = "LIGHTPINK";
}
else if(arrayData[j].key=="47")
{
country = "3";
color = "LIGHTSALMON";
}
else
{
country = "UK";
color = "DARKKHAKI";
}
check+='<a class="btn btn-success" style="background-color : ' + color + ';" href="<?php echo base_url()?>responsible/uk_pdf/'+arrayData[j].value+'">'+country+
'</a>|';
}
check +='</td></tr>';
}
check += '</tbody>'+
'</table>'+
'</div>';
if (row.child.isShown())
{
tr.next('tr').removeClass('details-row');
row.child.hide();
tr.removeClass('shown');
}
else
{
row.child(check).show();
tr.next('tr').addClass('details-row');
tr.addClass('shown');
}
});
});
function sortObject(obj)
{
var arr = [];
console.log(arr);
for (var prop in obj)
{
if (obj.hasOwnProperty(prop))
{
arr.push({
'key': prop,
'value': obj[prop]
});
}
}
arr.sort(function(a, b) { return a.value - b.value; });
return arr;
}
In all 3 slip_tables emp_id is common. then in each table having ORG_ID column. for UK having ORG_ID = 40, for GERMANY = 57, for POLAND = 47. In uk_slip having column pay_period for getting MONTH and YEAR with mysql functions MONTH and YEAR. and in germany and poland having pay_from to get the same.
I have a table in which I want to implement server side pagination.
Currently what I am doing is I am fetching entire data in one go (40-50k records) and assigning it to an array ($batchesData) and I have implemented a pager plugin of the jquery table sorter on it which is technically wrong because it slows down the system.
I want to implement server side pagination wherein only 10 records per page are fetched and displayed with this library but need some leads on how to proceed
This is how my tpl file looks like
<table class="table table-striped projects tablesorter"
id="batchTable" style="font-size: 13px;">
<th>
.....
.....
</th>
<tbody>
{if !empty($batchesData)}
{foreach from = $batchesData key = filter item = value}
<tr>
......
......
</tr>
{/foreach}
</tbody>
</table>
Pager code
<div style = "margin-left:30%" id="pager" class="tablesorterPager" >
<form>
<img src="/assets/images/first.png" width = "5%" height = "auto" class="first"/>
<img src="/assets/images/previous.png" width = "5%" height = "auto" class="prev"/>
<input type="text" class="pagedisplay"/>
<img src="/assets/images/next.png" width = "5%" height = "auto" class="next"/>
<img src="/assets/images/last.png" width = "5%" height = "auto" class="last"/>
<select class="pagesize">
<option selected="selected" value="10">10</option>
<option value="5">5 per page</option>
<option value="50">50 per page</option>
<option value="100">100 per page</option>
</select>
</form>
</div>
Js Code
/**
* To sort table columns in asc/desc order in Batch Listing View
*/
$('#batchTable')
.tablesorter({widthFixed: true, widgets: ['zebra']}) ;
/**
* To apply pagination in Batch Listing View
*/
$('#batchTable')
.tablesorterPager({container: $("#pager")});
Any leads would be highly appreciated
pager.js
(function($) {
$.extend({
tablesorterPager: new function() {
function updatePageDisplay(c) {
var s = $(c.cssPageDisplay,c.container).val((c.page+1) + c.seperator + c.totalPages);
}
function setPageSize(table,size) {
var c = table.config;
c.size = size;
c.totalPages = Math.ceil(c.totalRows / c.size);
c.pagerPositionSet = false;
moveToPage(table);
fixPosition(table);
}
function fixPosition(table) {
var c = table.config;
if(!c.pagerPositionSet && c.positionFixed) {
var c = table.config, o = $(table);
if(o.offset) {
c.container.css({
position: 'realtive'
});
}
c.pagerPositionSet = true;
}
}
function moveToFirstPage(table) {
var c = table.config;
c.page = 0;
moveToPage(table);
}
function moveToLastPage(table) {
var c = table.config;
c.page = (c.totalPages-1);
moveToPage(table);
}
function moveToNextPage(table) {
var c = table.config;
c.page++;
if(c.page >= (c.totalPages-1)) {
c.page = (c.totalPages-1);
}
moveToPage(table);
}
function moveToPrevPage(table) {
var c = table.config;
c.page--;
if(c.page <= 0) {
c.page = 0;
}
moveToPage(table);
}
function moveToPage(table) {
var c = table.config;
if(c.page < 0 || c.page > (c.totalPages-1)) {
c.page = 0;
}
renderTable(table,c.rowsCopy);
}
function renderTable(table,rows) {
var c = table.config;
var l = rows.length;
var s = (c.page * c.size);
var e = (s + c.size);
if(e > rows.length ) {
e = rows.length;
}
var tableBody = $(table.tBodies[0]);
// clear the table body
$.tablesorter.clearTableBody(table);
for(var i = s; i < e; i++) {
//tableBody.append(rows[i]);
var o = rows[i];
var l = o.length;
for(var j=0; j < l; j++) {
tableBody[0].appendChild(o[j]);
}
}
fixPosition(table,tableBody);
$(table).trigger("applyWidgets");
if( c.page >= c.totalPages ) {
moveToLastPage(table);
}
updatePageDisplay(c);
}
this.appender = function(table,rows) {
var c = table.config;
c.rowsCopy = rows;
c.totalRows = rows.length;
c.totalPages = Math.ceil(c.totalRows / c.size);
renderTable(table,rows);
};
this.defaults = {
size: 10,
offset: 0,
page: 0,
totalRows: 0,
totalPages: 0,
container: null,
cssNext: '.next',
cssPrev: '.prev',
cssFirst: '.first',
cssLast: '.last',
cssPageDisplay: '.pagedisplay',
cssPageSize: '.pagesize',
seperator: "/",
positionFixed: true,
appender: this.appender
};
this.construct = function(settings) {
return this.each(function() {
config = $.extend(this.config, $.tablesorterPager.defaults, settings);
var table = this, pager = config.container;
$(this).trigger("appendCache");
config.size = parseInt($(".pagesize",pager).val());
$(config.cssFirst,pager).click(function() {
moveToFirstPage(table);
return false;
});
$(config.cssNext,pager).click(function() {
moveToNextPage(table);
return false;
});
$(config.cssPrev,pager).click(function() {
moveToPrevPage(table);
return false;
});
$(config.cssLast,pager).click(function() {
moveToLastPage(table);
return false;
});
$(config.cssPageSize,pager).change(function() {
setPageSize(table,parseInt($(this).val()));
return false;
});
});
};
}
});
// extend plugin scope
$.fn.extend({
tablesorterPager: $.tablesorterPager.construct
});
})(jQuery);
Library Used - http://tablesorter.com/docs/
http://tablesorter.com/docs/example-pager.html
I made a TicTacToe Game! Just for fun. It works and all, but can't tell once someone has won. I used .inArray to look for winning solutions on the current board. The idea is once a winning combination of squares is on the board, an alert will pop up ("You won Bruh"). Maybe the inArray is comparing the win arrays to the chosen elements opposed to the elements of the win arrays to the chosen elements? I'm stumped. Check out the jsfiddle if you're interested and leave a response if you've figured it out. Thanks. http://jsfiddle.net/QH6W9/7/
//UPDATE
I ended up using a magic square and checking if combinations of 3 added to 15 and implemented self teaching and basic AI using possible combinations and a MySQL db. I used a second script to let the computer play itself and build up the database. It's not the most perfect code but see for yourself..
//---//--//--//--//--//--//---//--//--//--//--//---//
// TIC-TAC-TOE: //
//Good Old game. This version is meant to be a self//
//teaching system as a means to utilise and master //
//exchange between web-page, server and database. //
//---//--//--//--//--//--//---//--//--//--//--//---//
// Author: Dylan Madisetti
// Date: I don't remember?
$(document).ready(function(){
var magiclist = [8,3,4,1,5,9,6,7,2]; //for humans
var squares = [8,3,4,1,5,9,6,7,2]; //Le Magic Square\\
var xs = []; //------------//
var os = []; // 8 | 3 | 4 //
var x = 0; //----+---+---//
var o = 0; // 1 | 5 | 9 //
var gameover = -1; //----+---+---//
var FirstMoves = []; // 6 | 7 | 2 //
var SecondMoves = []; //------------//
var ThirdMoves = []; //All Diagonals,rows and Columns add to 15\\
var moves = [];
var i = 0;
win = false;
end = false;
// I have a radio button for whether the human plays as x or o
if(document.getElementById('human').checked) {
humanmove("x",x,xs,moves,squares,gameover,i,magiclist,"o",o,os); //human move
}else{
ajaxmove("x",x,xs,moves,squares,gameover,i,magiclist,"o",o,os); //computer move
x++;
i++;
humanmove("o",o,os,moves,squares,gameover,i,magiclist,"x",x,xs); //human move
};
});
//---//--//--//--//--//--//--//--//--//--//--//---//
// AjaxMove Desc. Checks if can win or block if it//
//can't, Sends data to MYSQLtest which in turn //
//queries xos database and returns best move is //
//then used. //
//---//--//--//--//--//--//--//--//--//--//--//---//
function ajaxmove(status,counter,turn,moves,squares,gameover,i,magiclist,otherturn){
bestmove = 0;
if (turn.length >= 2){ //goes through each possibility
FirstMoves = turn.slice(0);
while (FirstMoves.length > 1){
FirstX = FirstMoves[0];
SecondMoves = FirstMoves.slice(1);
ThirdMoves = squares.slice(0);
$.each (SecondMoves,function(){
if (ThirdMoves.length > 0){
SecondX = this;
$.each (ThirdMoves,function(){
ThirdX = this;
if (FirstX + SecondX + ThirdX == 15){
bestmove = this;
};
});
ThirdMoves = ThirdMoves.slice(1);
};
});
FirstMoves = FirstMoves.slice(1);
}
};
if ((bestmove == 0) && (otherturn.length >= 2)){
FirstMoves = otherturn.slice(0);
while (FirstMoves.length > 1){
FirstX = FirstMoves[0];
SecondMoves = FirstMoves.slice(1);
ThirdMoves = squares.slice(0);
$.each (SecondMoves,function(){
if (ThirdMoves.length > 0){
SecondX = this;
$.each (ThirdMoves,function(){
ThirdX = this;
if (FirstX + SecondX + ThirdX == 15){
bestmove = this;
};
});
ThirdMoves = ThirdMoves.slice(1);
};
});
FirstMoves = FirstMoves.slice(1);
}
};
if (bestmove == 0){
$.ajax({type:'POST',
async: false,
url:'/XOsAI/MYSQLtest.php',
data:{
status: status,
moves: moves,
remaining: squares,
gameover: gameover
},
success:
function(data){
bestmove = data;
}
});
};
bestmove = Number(bestmove);
index = squares.indexOf(bestmove);
turn[counter] = bestmove;
select = magiclist.indexOf(bestmove);
$('.square').eq(select).addClass(status);
$('.square').eq(select).addClass('clicked');
squares.splice(index,1);
moves[i] = turn[counter];
gamecheck(turn,squares,moves); //game check (see below)
if (win) {
alert ("You Lose!");
while (i <= 9){
i++;
moves[i] = "'" + status + "'";
};
$.ajax({type:'POST',
async: false,
url:'/XOsAI/MYSQLtest.php',
data:{
status: status,
moves: moves,
remaining: squares,
gameover: gameover
}
});
};
};
//---//--//--//--//--//--//--//--//--//--//--//---//
// HumanMove Desc. Allows human to make a move and//
//checks if they have won.Updates Database if so. //
//Also Triggers computer move. //
//---//--//--//--//--//--//--//--//--//--//--//---//
function humanmove(status,counter,turn,
moves,squares,gameover,
i,magiclist,otherstatus,
othercounter,otherturn){
$(".XOs").on('click', '.square:not(.clicked)', function() {
if (gameover == -1){
if (!$(this).hasClass("clicked")) {
$(this).addClass('clicked');
$(this).addClass(status);
data = magiclist[$('.square').index(this)];
turn[counter] = data;
index = squares.indexOf(data);
squares.splice(index,1);
moves[i] = turn[counter];
gamecheck(turn,squares,moves); //game check (see below)
if (!(end)){
if (win) {
alert ("You Win!");
gameover = 1;
while (i <= 9){
i++;
moves[i] = "'" + status + "'";
};
$.ajax({type:'POST',
async: false,
url:'/XOsAI/MYSQLtest.php',
data:{
status: status,
moves: moves,
remaining: squares,
gameover: gameover
}
});
$('.squares').addClass('clicked');
};
counter++;
i++;
if (gameover == -1){
ajaxmove(otherstatus,othercounter,otherturn,moves,squares,gameover,i,magiclist,turn); //computer move
othercounter++;
i++;
if (win) {gameover = 1;};
};
};
};
};
});
};
//---//--//--//--//--//--//--//--//--//--//--//---//
// GameCheck Desc. Runs through each possibility.//
//As data locations of divs are arranged in magic //
//square, checks if any three add to 15. Checks //
//for cat game as well. //
//---//--//--//--//--//--//--//--//--//--//--//---//
function gamecheck(turn,squares,moves){
if (turn.length >= 3){
FirstMoves = turn.slice(0);
while (FirstMoves.length >= 3){
FirstX = FirstMoves[0];
SecondMoves = FirstMoves.slice(1);
ThirdMoves = SecondMoves.slice(1);
$.each (SecondMoves,function(){
if (ThirdMoves.length > 0){
SecondX = this;
$.each (ThirdMoves,function(){
ThirdX = this;
if (FirstX + SecondX + ThirdX == 15){
win = true;
};
});
ThirdMoves = ThirdMoves.slice(1);
};
});
FirstMoves = FirstMoves.slice(1);
}
};
if (!(squares.length > 0) && win == false) { //if any remain
alert ("You Draw!");
gameover = 1;
moves[9] = "'c'";
$.ajax({type:'POST', //ajax to tell server Cat Game
async: false,
url:'/XOsAI/MYSQLtest.php',
data:{
status: "c",
moves: moves,
remaining: squares,
gameover: gameover
}
});
end = true;
};
};
and the php if anyone is interested
//--------------------------------------------------------------------------
// 1) Connect to mysql database
//--------------------------------------------------------------------------
$con = mysqli_connect($host,$user,$pass,$databaseName);
$dbs = mysqli_select_db($con,$databaseName);
//--------------------------------------------------------------------------
// 2) Query database for bestmove or insert data if gameover
//--------------------------------------------------------------------------
$gameover = 0;
$col = 0;
$status = $_POST['status'];
$moves = $_POST['moves'];
$gameover = $_POST['gameover'];
$remaining = $_POST['remaining'];
$bestresult = 0;
if ($gameover < 0){
$required = (count($remaining) * 50); //seemed large enough to make a smart move
if (count($moves) > 0){
foreach ($moves as $move){
$columns[$col].=' AND ';
$columns[$col].= '`';
$columns[$col].= ($col + 1);
$columns[$col].= '`=';
$columns[$col].= $move;
$col++;
};
$moves = implode(' ',$columns);
};
$sql = '
SELECT *
FROM xos
WHERE status=\'';
$sql .= $status;
$sql .= '\' ';
if (count($moves) > 0){
$sql .= $moves ;
};
$results = mysqli_query($con,$sql); //fetch result
$results = $results->num_rows;
echo $con->error;
if ($results > $required){
if (count($moves) == 0){
$col = 1;
};
$reset = $sql;
foreach ($remaining as $bestmove){
$sql .=' AND ';
$sql .= '`';
$sql .= $col;
$sql .= '`=';
$sql .= $bestmove;
$sql .= ' ';
$results = mysqli_query($con,$sql);
$results = $results->num_rows;
if ($con->error){
echo $con->error ."\n";
echo $sql .":";
echo $results ."\n \n";
}
if ($results >= $bestresult){
$bestresult = $results;
$bestplay = $bestmove;
};
$sql = $reset;
};
}else{
$sql = '
SELECT *
FROM xos
WHERE status=\'c\'';
if (count($moves) > 0){
$sql .=' AND ';
$sql .= $moves ;
};
$results = mysqli_query($con,$sql); //fetch result
$results = $results->num_rows;
if ($results > $required){
if (count($moves) == 0){
$col = 1;
};
$reset = $sql;
foreach ($remaining as $bestmove){
$sql .=' AND ';
$sql .= '`';
$sql .= $col;
$sql .= '`=';
$sql .= $bestmove;
$sql .= ' ';
$results = mysqli_query($con,$sql);
$results = $results->num_rows;
if ($con->error){
echo $con->error ."\n";
echo $sql .":";
echo $results ."\n \n";
}
if ($results >= $bestresult){
$bestresult = $results;
$bestplay = $bestmove;
};
$sql = $reset;
};
}else{
$max = count($remaining) - 1;
$bestplay = rand(0,$max);
$bestplay= $remaining[$bestplay];
};
};echo $bestplay;
}else{
$sql = "INSERT INTO `xos`(`1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `Status`) VALUES (";
for ($i = 0; $i <= 8; $i++) {
$sql .= $moves[$i];
$sql .= ",";
};
$sql .= "";
$sql .= $moves[9];
$sql .= ")";
if ($con->query($sql) === false){
echo $con->error;
echo $sql;
};
};
At first glance, it looks like in
$(wins).each(function(){
var maybe = $.inArray(this,xs); //if Xs match combos win
...
}
you're checking if the array xs is found in the currently checked winning combination instead of just comparing this to xs (both 1-dimensional arrays). [Tried $.inArray(wins, xs) but it won't work.]
Could this be it?
UPDATE: this version works: http://jsfiddle.net/QH6W9/9/
I fixed your code to retrieve the ids of the X'ed fields with this:
var xs = $(".x").map(function(i, el) {
return parseInt($(el).attr('id'))
}).get(); // get ids as array
And also the detection of the win situation:
$(wins).each(function() {
var found = true;
for(var i =0; i<this.length; i++) {
found &= ($.inArray(this[i], xs) > -1);
}
if (!found) return;
alert("You Won Bruh");
var all = $(".square");
$(all).addclass('clicked'); //stops more turns
return;
});
You have a couple of issues.
First, you are putting all of the locations of .x into an array, and then seeing if that array is in the wins array.
Unfortunately, $.inArray() will only return an index if the items are the same item, not if they have matching values.
$.inArray([4,5,6], [[1,2,3], [4,5,6]]) // returns -1
var ary1 = [1,2,3];
var ary2 = [4,5,6];
$.inArray(ary2, [ary1, ary2]); // returns 1
$.inArray(ary2, [ary1, [4,5,6]]); // returns -1
Secondly, if you are at a state in the game where you have more than 3 X's, you will never match a winning position:
X O _
X X O
X O _
In this case xs will equal [1,4,5,7]. This is a winning position, but will not match any of your arrays.
There are a number of other ways to go about this. The easiest, given your wins array, is to iterate through each and check if the div at each location in the array is an X. If so, stop and declare a win.
Demo: http://jsfiddle.net/jtbowden/4BDwt/1/
Note, I cleaned up some other code in this example.
Removed the redundant clickable class, and use
.square:not(.clicked).
Replaced .click() with .on().
Removed the .square IDs and just use the div order in XOs as the location, using .eq() with the array position. IDs shouldn't start with numbers, and it is better to store data in a jQuery data attribute, like <div data-location="1">, and retrieve it with .data('location'). But, in this case, it wasn't needed as the div order tells us where it is.
Replaced $(array).each(function(){}) with $.each(array, function(){}). This is the correct way to iterate over a normal array that is not jQuery objects.
You had two problems in your program:
First, you had the following:
parseInt(number);
xs[i] = number;
xs[i] was still getting a string because parseInt() does not modify its parameter. Instead, it returns the numeric value. So I changed that code to the more compact:
xs[i] = parseInt(number);
Secondly, in your $(wins).each() loop, you were using $.inArray(), but you already have the individual array, so you really wanted to do an array subset comparison there. Since Javascript/jQuery has no built-in array subset function, I just compared each element in the array:
$(wins).each(function(){
console.log( 'template: ' + this );
var allIn = true;
for( var i=0; i<this.length; i++ ) {
console.log( this[i] );
if( $.inArray( this[i], xs ) == -1 ) allIn = false;
}
if ( allIn ){
alert("You Won Bruh");
And now it works. I only did it for X's, not for O's...I'll leave that up to you! You can see my jsfiddle solution here:
http://jsfiddle.net/HxGZE/2/
EDIT: my solution now works. See the jsfiddle for proof.