Calculate input field based on expiry date - javascript

A form with 50 entries: each with P1-48, E1-48, and X1-48. I want to calculate the Entry Fee "E1" based on the expires date X1. The js date format for the expires date is YYYY.MM.DD, ex. 2018.04.21 and a player pays $3 if his expires date is greater or equal to today's date. He pays $5 if his expires date is older or less than today's date. But if the expires date is blank and the player pays a membership fee, the Entry Fee is waived to zero.
JS:
<script src = "js/moment.min.js"></script>
I also have this as a "template" starting guide. I think it could be modified and piggyback the target result onto it.
<script> // change expiration date color
function getExpireDate(ele) {
var i = null;
for (i = 0; members.length > i; i++) {
if (members[i].Name == ele.value) {
var exDate = moment(members[i].Expires, 'YYYY.MM.DD');
if (moment().isAfter(exDate)) {
$(ele).closest('.universal').find('.expDate').css('color', "#A3005B");
} else {
$(ele).closest('.universal').find('.expDate').css('color', "#275052");
}
return members[i].Expires;
}
}
return '';
}
</script>
<script>
for (let i = 0; i <= 48; i++) {
$("#P" + i).on("blur", function(){
$("#X" +i).val(getExpireDate(this));
});
}
</script>
<script>
var members [
{"Name": "Jones, David", "Expires": "2017.05.03" },
{"Name": "Roth, Bill", "Expires": "2017.03.08" },
{"Name": "Scullin, Kenn", "Expires": "2019.02.20" }
]
<script>
HTML:
<div>
<input type = "text" id = "P1"> <!--Player-->
<input type = "text" id = "E1"> <!--Entry Fee-->
<input type = "text" id = "M1"> <!--Membership Fee-->
<input type = "text" id = "X1" onblur="getExpireDate()" class="expDate"> <!--expires-->
<div>
Funny thing is:
<input type = "text" onblur="getClass()" class="text" id="Y1" maxlength = "4" size = "4" disabled /> <!--works even with input disabled -->
<input type = "text" onblur="calcEntryFee(this);" class="expDate" name = "exp" id="X1" maxlength = "10" size = "10" disabled /><!--new code doesn't work -->
<script> // Lookup class or rating
function getClass(ele) {
var i = null;
for (i = 0; members.length > i; i++) {
if (members[i].Name == ele.value) {
return members[i].Rating;
}
}
return;
}
for (let i = 0; i <= 48; i++) {
$("#P" + i).on("blur", function(){
$("#Y" +i).val(getClass(this));
});
}
</script>

How about this:
(The main function is calcEntryFee().)
var members = [
// ... fill data here.
];
function getMemberData( name ) {
var a = jQuery.trim( name ).toLowerCase(),
i, b, member;
for ( i = 0; i < members.length; i++ ) {
b = jQuery.trim( members[ i ].Name ).toLowerCase();
if ( a === b ) {
member = members[ i ];
break;
}
}
return member || {};
}
function calcEntryFee( elem ) {
var idx, member, exDate, today, fee;
elem = elem || {};
if ( /^[PEMX](\d+)$/.test( elem.id ) ) {
idx = RegExp.$1;
} else {
return false;
}
member = getMemberData( jQuery( '#P' + idx ).val() );
mmfee = parseFloat( jQuery( '#M' + idx ).val() );
exDate = moment( member.Expires, 'YYYY.MM.DD' );
today = moment();
fee = '';
if ( exDate.isBefore( today ) ) {
fee = 5;
} else if ( exDate.isSameOrAfter( today ) ) {
fee = 3;
} else if ( ! member.Expires && mmfee > 0 ) {
fee = 0;
}
// Updates the entry fee input value.
jQuery( '#E' + idx ).val( fee );
return fee;
}
You'd use calcEntryFee() like this:
<input id="X1" placeholder="X" size="10" onblur="calcEntryFee( this );" />
See the full code and try a live demo on https://codepen.io/anon/pen/WJRNVY.
UPDATE
Because the expiry date field/input is disabled, use this instead: (take note of the id value, which could also be P2, P3, etc.)
<input id="P1" placeholder="P" onblur="calcEntryFee( this );" />
I.e. Add the calcEntryFee( this ); to the onblur attribute of the "Player" field and not the expiry date field. Or add it to any sibling/related fields which is not disabled, or which we can tab to. (So that we can focus and "un-focus" or blur on the field, and the browser would then invoke the calcEntryFee( this ); that was attached to the field's blur event.)
Try a live demo on: https://codepen.io/anon/pen/xjgQyx
Alternatively, you may add it without using the onblur attribute of the input/field: (refer to the code you provided in your question)
for (let i = 0; i <= 48; i++) {
$("#P" + i).on("blur", function() {
$("#X" + i).val(getExpireDate(this));
calcEntryFee(this); // <- add it here
});
}

Had to re-read your question a few times. I'm still not sure a fully understand what you're trying to achieve, but I believe this is pretty close:
let getMember = {
index: function(name) {
let index = -1;
$.each(members, function(i, player) {
if (player.Name === name) { index = i; }
});
return index;
},
entryFee: function(memberIndex) {
if (memberIndex === -1) {
return 'waived';
} else {}
let today = new Date();
let expires = new Date(members[memberIndex].Expires.replace(/\./g, '-'));
return today <= expires ? '$3' : '$5';
}
};
let members = [
{"Name": "Jones, David", "Expires": "2017.05.03" },
{"Name": "Roth, Bill", "Expires": "2017.03.08" },
{"Name": "Scullin, Kenn", "Expires": "2019.02.20" }
];
let tableHTML = '';
for (let i=0; i < 50; i++) {
tableHTML += `
<div class="row">
<input type="text" class="player" placeholder="player">
<input type="text" class="entryFee" placeholder="entry fee">
<input type="text" class="membershipFee" placeholder="membership fee">
<input type="text" class="expDate" placeholder="expire date">
<div>`;
}
$(`<div class="table">${tableHTML}</div>`)
.appendTo('body')
.on('blur', '.player', function() {
if (!this.value) { return false; }
let memberIndex = getMember.index(this.value);
let entryFee = getMember.entryFee(memberIndex);
$(this)
.next().val(entryFee)
.next().val(entryFee === 'waived' ? 'yes' : 'no')
.next()
.val(memberIndex >= 0 ? members[memberIndex].Expires : 'non-member')
.addClass(entryFee === '$3' ? 'currentMember' : 'nonCurrentMember');
$('.player').eq($('.player').index(this) + 1).focus();
});
https://jsfiddle.net/ypzjfkxk/
Without an external library to boot! Can't say I have any experience with moment.js, but all of the questions I've come across seem to be solvable in plain javascript. Also, it would be just as fast and easy to generate an alphabetical table for this. Then you wouldn't have to worry about typos in the player input. Unless you're trying to create a log or something?

This works for me:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.js"></script>
<script type="application/javascript">
var members = [
{"Name": "Jones, David", "Expires": "2017.05.03" },
{"Name": "Scullin, Kenn", "Expires": "2019.02.20" },
{"Name": "Peter, Kenn", "Expires": "2018.04.24" },
{"Name": "Chris, Kennx", "Expires": "" }
];
$(document).ready(function(){
var nUsers = 4; // Number os users
// Fill inputs (tmp: visual purpose)
for (count=1; count<=nUsers; count++){
$("#P"+count).val(members[count-1].Name);
$("#X"+count).val(members[count-1].Expires);
}
$("#M4").val("$20");
/* Get current date. For security purpose you should
get this from the server and not the client side.*/
var date = moment().toDate();
// Go through every input row
for (count=1; count<=nUsers; count++){
var exDate = $("#X"+count).val(); // Get the exire date
// Confirm that date is has the right format
if (moment(exDate, 'YYYY.MM.DD').isValid()){
exDate = moment(exDate, 'YYYY.MM.DD').toDate();
var diff = new Date(exDate - date);
var nDays = parseInt(diff/1000/60/60/24);
console.log(nDays);
if (nDays >= 0){ // If his expires date is greater or equal to today's date
$("#E"+count).val("$3");
$("#X"+count).css('color', "#275052");
}
if (nDays < 0){
$("#E"+count).val("$5"); // If his expires date is older or less than today's date
$("#X"+count).css('color', "#A3005B");
}
}
else{ // If expire date is empty
var mFee = parseFloat($("#M"+count).val().replace(/\$/, ''));
if ((exDate.length == 0) && (mFee > 0 )){ // If the expires date is blank and the player pays a membership fee
$("#E"+count).val("$0");
}
}
}
});
</script>
</head>
<body>
<!-- visual purpose -->
<div>
<input type = "text" id = "P1"> <!--Player-->
<input type = "text" id = "E1"> <!--Entry Fee-->
<input type = "text" id = "M1"> <!--Membership Fee-->
<input type = "text" id = "X1" class="expDate"> <!--expires-->
<br>
<input type = "text" id = "P2"> <!--Player-->
<input type = "text" id = "E2"> <!--Entry Fee-->
<input type = "text" id = "M2"> <!--Membership Fee-->
<input type = "text" id = "X2" class="expDate"> <!--expires-->
<br>
<input type = "text" id = "P3"> <!--Player-->
<input type = "text" id = "E3"> <!--Entry Fee-->
<input type = "text" id = "M3"> <!--Membership Fee-->
<input type = "text" id = "X3" class="expDate"> <!--expires-->
<br>
<input type = "text" id = "P4"> <!--Player-->
<input type = "text" id = "E4"> <!--Entry Fee-->
<input type = "text" id = "M4"> <!--Membership Fee-->
<input type = "text" id = "X4" class="expDate"> <!--expires-->
<div>
</body>
</html>
And a recommendation that I gave to you in the code is you should get the current time from the server side and not from the client side.
I hope that works for you. :)

Related

How to sort a multi dimensional array output in ascending order?

My code generates a two dimensional matrix when the OK is clicked. The code stores the data in the multidimensional array, but I am trying to add a sort function to the code which rearranges the code in ascending order using the 4th text box. Any suggestions on how I can do that ?
HTML Code
<div class="rightDiv">
<div id = "pastcalcblock">
<h3> PAST CALCULATIONS </h3>
<input type = "text" size = "1" id = "text1"/>
<input type = "text" size = "1" id = "text2"/>
<input type = "text" size = "1" id = "text3"/>
<input type = "text" size = "1" id = "text4"/><br>
<input type = "button" value = "Ok" id = "operation" onClick = "display()"/>
<div id = "resultTab">
SORT<br>
<input type = "button" value = "As Entered" id = "enteredBut">
<input type = "button" value = "By Result" id = "resultBut" onClick = "sort()"><br><br>
<div id="expressions">
</div>
</div>
</div>
Javascript Code
function display()
{
var arrayOne =[document.getElementById('text1').value,document.getElementById('text2').value,document.getElementById('text3').value,document.getElementById('text4').value ];
new_array=arrayOne.join(" ");
var para = document.createElement("p");
var t = document.createTextNode(new_array);
para.appendChild(t)
document.getElementById("expressions").appendChild(para);
}
function sort(){
var dispArr = [document.getElementById('text1').value,
document.getElementById('text2').value, document.getElementById('text3').value,document.getElementById('text4').value];
var myArray = [];
for(var i = 0 ; i < 1 ; i ++ ) {
myArray[i] = [];
for(var j = 0 ; j < 5 ; j++ )
{
myArray[i][j] = dispArr[j];
console.log(myArray[i][j]);
}
}
}
You would better keep the whole matrix in a memory variable, and add to that. Also consider that when the output is sorted, you must know how to get back to the original order also, so that the "As Entered" button still has the desired effect. So, it is better to have a display function that starts from scratch, empties the output and reproduces all the data in either entered or sorted order.
Here is how you could do that:
var matrix = []; // global value with all data
function addExpression() {
var arrayOne = [
document.getElementById('text1').value,
document.getElementById('text2').value,
document.getElementById('text3').value,
document.getElementById('text4').value
];
// add to matrix
matrix.push(arrayOne);
display(false);
}
function display(byResult) {
// Determine whether to sort or not:
var matrix2 = byResult ? sorted(matrix) : matrix;
// display each row:
var expressions = document.getElementById("expressions");
expressions.innerHTML = ''; // empty completely
matrix2.forEach( row => {
var para = document.createElement("p");
var t = document.createTextNode(row.join(" "));
para.appendChild(t)
expressions.appendChild(para);
});
}
function sorted(m){ // Create a copy, and sort that by last column
return m.slice().sort( (a, b) => a[3] - b[3] );
}
<div class="rightDiv">
<div id = "pastcalcblock">
<h3> PAST CALCULATIONS </h3>
<input type = "text" size = "1" id = "text1"/>
<input type = "text" size = "1" id = "text2"/>
<input type = "text" size = "1" id = "text3"/>
<input type = "text" size = "1" id = "text4"/><br>
<input type = "button" value = "Ok" id = "operation" onClick = "addExpression()"/>
<div id = "resultTab">
SORT<br>
<input type = "button" value = "As Entered" id = "enteredBut" onClick="display(false)">
<input type = "button" value = "By Result" id = "resultBut" onClick = "display(true)"><br><br>
<div id="expressions">
</div>
</div>
</div>
</div>

How to retrieve session storage values and pass it to radio buttons and checkboxes?

As the question is asking, can you get the values from the session storage or local storage to radio buttons on html and the same thing for the checkboxes?
My code:
var customername = {"firstname" : getCookie("firstname"), "lastname" : getCookie("lastname")};
var curcustomer1 = {"firstname" : getCookie("firstname"), "lastname" : getCookie("lastname")};
var lastvist = {"date" : dateall} // only display the date and time
var myJSON = JSON.stringify(customername);
var myJSON1 = JSON.stringify(lastvist); // has the date when the user last has visited
var myJSON2 = JSON.stringify(curcustomer1);
var myJSON3full = JSON.stringify(custinfo);
sessionStorage.setItem("custinfo", myJSON3full);
var objectfull = sessionStorage.getItem("custinfo");
objfull = JSON.parse(objectfull);
var object = sessionStorage.getItem("customername");
obj = JSON.parse(object);
if(object != myJSON) {
sessionStorage.setItem("customername", myJSON);
var object = sessionStorage.getItem("customername");
obj = JSON.parse(object);
var curcustomer = customername;
var myJSONcopy = JSON.stringify(curcustomer);
var object2 = sessionStorage.setItem("curcustomer", myJSONcopy);
var msg5 = "Welcome ";
document.getElementById("customer").innerHTML = msg5 + " " + "New Customer";
document.getElementById("date1").innerHTML = "";
var radiobtn = document.getElementsByName("type");
if(radiobtn.value != 8) {
document.elem.type.value="8";
}
var radiobtn1 = document.getElementsByName("special");
if(radiobtn1.value != 0) {
document.elem.special.value="0";
}
for (var i = 0; i < extras.length; i++) {
if (extras[i].checked) {
extras[i].checked = false;
}
}
}
if(object == myJSONcopy) {
radiobtn = document.getElementsByClassName("type").innerHTML = sessionStorage.getItem("type");
radiobtn1 = document.getElementsByClassName("special").innerHTML = sessionStorage.getItem("special");
checboxes = document.getElementsByClassName("extras").innerHTML = sessionStorage.getItem("extras");
}
<td>
<input type="radio" name="type" value="8" checked>Small $8.00
<br>
<input type="radio" name="type" value="10">Medium $10.00
<br>
<input type="radio" name="type" value="15">Large $15.00
<br>
<input type="radio" name="type" value="18">Extra Large $18.00
<br>
<br>
</td>
if you are trying to add the item to multiple buttons that share the same className then you will have to do something like this:
var list = document.getElementsByClassName('type');
var i;
for (i = 0; n < list.length; ++i) {
list[i].value= sessionStorage.getItem('events')
};
But if it's just one button then I will suggest you use getElementById
like this
document.getElementById('Id').value = sessionStorage("events");

Make calculation based on information provided

I am building a website and I want to do calculations based on information provided. I obviously need to have information provided in two out of the three fields to calculate the third's value.
The three fields are:
Price Per Gallon
Gallons Bought
Total Sale
I obviously know that I can calculate the amount of gas bought by dividing the Total Sale amount by the Price Per Gallon.
However I want to calculate based on whatever two fields are entered. I am trying to find out the best way to do this.
I know this much:
Check to see which fields are empty
Determine which type of calculation to make
Here is what I have so far:
<form>
<input type="number" id="totalSale" placeholder="Total Sale Amount" class="calculate" />
<input type="number" id="gallonPrice" placeholder="Price Per Gallon" class="calculate" />
<input type="number" id="gallons" placeholder="Gallons" class="calculate" />
</form>
<script>
var e = document.getElementsByClassName("calculate");
function calc(){
var sale_amt = document.getElementById("totalSale");
var ppg = document.getElementById("gallonPrice");
var gallons = document.getElementById("gallons");
if (sale_amt || ppg !== null) {
var calc_gallons = sale_amt.value / ppg.value;
gallons.value = calc_gallons.toFixed(3);
}
}
for (var i = 0; i < e.length; i++) {
e[i].addEventListener('keyup', calc, false);
}
</script>
the logic should take into consideration which element is currently being entered (that will be this in calc). Also, you need to take into consideration what happens when all three have values, and you change one ... which of the other two should be changed?
See if this works for you
var sale_amt = document.getElementById("totalSale");
var ppg = document.getElementById("gallonPrice");
var gallons = document.getElementById("gallons");
function calc(){
var els = [sale_amt, ppg, gallons];
var values = [sale_amt.value, ppg.value, gallons.value];
var disabledElement = els.find(e=>e.disabled);
var numValues = els.filter(e => e.value !== '' && !e.disabled).length;
var calc_gallons = function() {
gallons.value = (values[0] / values[1]).toFixed(3);
};
var calc_ppg = function() {
ppg.value = (values[0] / values[2]).toFixed(3);
};
var calc_sale = function() {
sale_amt.value = (values[1] * values[2]).toFixed(2);
};
if (numValues < 3) {
if (numValues == 1 && disabledElement) {
disabledElement.disabled = false;
disabledElement.value = '';
disabledElement = null;
}
els.forEach(e => e.disabled = e == disabledElement || (numValues == 2 && e.value === ''));
}
disabledElement = els.find(e=>e.disabled);
switch((disabledElement && disabledElement.id) || '') {
case 'totalSale':
calc_sale();
break;
case 'gallonPrice':
calc_ppg();
break;
case 'gallons':
calc_gallons();
break;
}
}
var e = document.getElementsByClassName("calculate");
for (var i = 0; i < e.length; i++) {
e[i].addEventListener('keyup', calc, false);
e[i].addEventListener('change', calc, false);
}

Drop down box text disappears after completing a function, how can I get it to display what option was chosen?

The functions below work fine, the only thing I need help with is that when I pick an option from a drop down menu, it runs the function, but it erases all of the options in the drop down box. How can I get it NOT to do that and continue displaying my original options in the same drop down box?
<script type="text/javascript">
function gbid(s) {
return document.getElementById(s);
}
function myCount() {
var excel = new ActiveXObject("Excel.Application");
var excel_file = excel.Workbooks.Open("somefilepathhere.xlsx");
var excel_sheet = excel.Worksheets("Sheet1");
var agent,count
agent=document.getElementById("tAgent").value;
if (agent=="Agent1")
{
count=gbid('tAgent').innerText = excel_sheet.Cells(1,1).Value;
}
else if (agent=="Agent2")
{
count=gbid('tAgent').innerText = excel_sheet.Cells(2,1).Value;
}
document.getElementById("disphere").innerHTML = count;
excel.Quit();
excel.Application.Quit();
}
function saveToExcel() {
var myApp = new ActiveXObject("Excel.Application");
myApp.visible = false;
var xlCellTypeLastCell = 11;
var x = document.forms["f1"]["tAgent"].value;
if (x == null || x == "") {
alert("You must select an 'Entered By' option!");
return false;
}
else
var myWorkbook = myApp.Workbooks.Open(filePath);
var myWorksheet = myWorkbook.Worksheets(1);
myWorksheet.Activate;
objRange = myWorksheet.UsedRange;
objRange.SpecialCells(xlCellTypeLastCell).Activate;
newRow = myApp.ActiveCell.Row + 1;
alert('A new log was created on row '+newRow);
strNewCell = "A" + newRow;
myApp.Range(strNewCell).Activate;
myWorksheet.Cells(newRow,1).value = f1.tMemberid.value;
myWorksheet.Cells(newRow,2).value = f1.tDate.value;
myWorksheet.Cells(newRow,3).value = f1.tRep.value;
myWorksheet.Cells(newRow,4).value = f1.tIssuerep.value;
myWorksheet.Cells(newRow,5).value = f1.tLOB.value;
myWorksheet.Cells(newRow,6).value = f1.tContactnum.value;
myWorksheet.Cells(newRow,7).value = f1.tMembername.value;
myWorksheet.Cells(newRow,8).value = f1.tIssid.value;
myWorksheet.Cells(newRow,9).value = f1.tTypeofissue.value;
myWorksheet.Cells(newRow,10).value = f1.tDiscofissue.value;
myWorksheet.Cells(newRow,11).value = f1.tTimesent.value;
myWorksheet.Cells(newRow,12).value = f1.tSendto.value;
myWorksheet.Cells(newRow,13).value = f1.tAgent.value;
myWorkbook.Close(true);
myApp.Workbooks.Close;
myApp.Close;
alert('Process Complete!');
}
</script>
<table >
<tr>
<td class="tb_bor" Align="center" ><h1>ACA Issues Tracker</h1><br />
<b>Entered By: </b>
<select name="tAgent" id="tAgent" style="80% !important;" onchange="myCount()">
<option value="" ></option>
<option value="Agent1" >Agent 1</option>
<option value="Agent2" >Agent 2</option>
</select>
<br />You have completed: <p id="disphere"></p>
<hr>
</td>
</tr>
</table>
With the below line you overwrite the inner text of your select field:
count = gbid( 'tAgent' ).innerText = excel_sheet.Cells( 1,1 ).Value;
^
|
Allthough I'm not clear on what you desire to achieve with the code because I don't understand your usecase, I think you might have mistaken the second equals sign with a string concatenation or something?
This might be what you tried to achieve:
count = gbid( 'tAgent' ).innerText + ' ' + excel_sheet.Cells( 1,1 ).Value;
This is a corrected version of your function:
function myCount() {
var excel = new ActiveXObject( 'Excel.Application' ),
excel_file = excel.Workbooks.Open( 'somefilepathhere.xlsx' ),
excel_sheet = excel.Worksheets( 'Sheet1' ),
agent = document.getElementById( 'tAgent' ).value,
count;
if ( agent === 'Agent1' ) {
count = excel_sheet.Cells( 1,1 ).Value;
} else if ( agent === 'Agent2' ) {
count = excel_sheet.Cells( 2,1 ).Value;
}
document.getElementById( 'disphere' ).innerHTML = count;
excel.Quit();
excel.Application.Quit();
}

JavaScript Sudoku ID fields not registering

I decided to see if I can create an online Sudoku game using HTML, JavaScript, CSS and PHP. So far, I've created the grid but I'm stumped as to why when I try to use an alert box to show their input, I'm either getting "undefined" (when I use .value), blank (when I use .innerText) or the HTML object (when I use .innerHTML). Either I'm missing my coffee but I cannot figure out why neither seem to be working.
My intention is when the user clicks on "Evaluate!", each of the hidden fields (1 for each row) will be populated in a comma-separated format. PHP will receive the content and can break it apart using explode(",", $row), allowing each to be compared as separate arrays against each other. But that's for later.
To save time when reading my code, the problematic area seems to be within the initGrid() function as that's where I'm creating the attributes. I should note, I've checked the console log and there are no errors. Also, I'm trying to do all of this using only JavaScript, not jQuery.
Here's a JSFiddle, although for some reason, my alert boxes aren't working in it but they are in my browser (Chrome, same browser I'm using for JSFiddle).
Here is the troublesome initGrid() function:
function initGrid() {
var table = document.getElementById("mainTable").getElementsByTagName("tbody")[0];
var atts = ["a", "b", "c", "d", "e", "f", "g", "h", "i"];
for (var i = 0; i < atts.length; i++) {
var newRow = table.insertRow(i);
for (var j = 0; j < 9; j++) {
var newCell = newRow.insertCell(j);
newCell.innerHTML = document.getElementById("defaultButtons").innerHTML;
newCell.setAttribute("name", atts[i] + j);
newCell.setAttribute("id", atts[i] + j);
newCell.setAttribute("value", "");
newCell.setAttribute("onKeyUp", "appendData(this.id, this)");
}
}
}
It maybe isn't clear from your fiddle - but from clicking the "Evaluate" button populateAllHidden() is never being called. In Chrome there is an error logged in the console:
Uncaught ReferenceError: populateAllHidden is not defined
Instead of using onclick in the button:
<button type="button" onClick="populateAllHidden()">Evaluate!</button>
You can give it an ID, and then register an event listener at the same time you initialize the grid. So change the button to:
<button type="button" id="evaluateButton">Evaluate!</button>
In the onload, add the event listener:
window.onload = function () {
initGrid();
document.getElementById("evaluateButton").addEventListener("click", populateAllHidden, false);
};
Give that a go - it worked for me!
After a nice long nap (had only a few hours of sleep when I tried to create the sudoku puzzle), I re-visited it and realized how much of a mess it was. I've since made much more progress and am working on the PHP aspect of it to generate a puzzle. There's also a simple on-screen verification that tells the user whether their input was valid (i.e. a number) or not. Hopefully it can also help someone else, below is sudokuGrid.php:
I just finished writing the verify function and I still have to sort out a few things with it.
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8" />
<title>Online Sudoku</title>
<script type = "text/javascript">
function initGrid() {
var tBody = document.getElementById("mainTable").getElementsByTagName("tbody")[0];
var rowLetters = ["a", "b", "c", "d", "e", "f", "g", "h", "i"];
for(var i = 0; i < rowLetters.length; i++) {
var newRow = tBody.insertRow(i);
var rowLabel = newRow.insertCell(0);
rowLabel.innerHTML = rowLetters[i];
rowLabel.style.padding = "0px 4px 0px 4px";
rowLabel.style.fontWeight = "bold";
for(var j = 1; j < 10; j++) {
var newCell = newRow.insertCell(j);
var newName = rowLetters[i] + j;
newCell.innerHTML = "<input type = 'text' class = 'sudokuCells' value = '' name = " + newName + " maxLength = '1' onInput = 'verify(this)' id = " + newName + " />";
}
}
}
function verify(x) {
var valid = document.getElementById("valid");
var invalid = document.getElementById("invalid");
valid.style.visibility = "hidden";
invalid.style.visibility = "hidden";
if(!isNaN(parseInt((x.value).slice(0, 1)))) {
valid.style.visibility = "visible";
invalid.style.visibility = "hidden";
} else if(((x.value).slice(0, 1)).trim().length == 0) {
invalid.style.visibility = "hidden";
valid.style.visibility = "hidden";
} else {
invalid.style.visibility = "visible";
valid.style.visibility = "hidden";
alert("Sorry, that was an invalid character");
x.value = "";
}
}
function populateAllHidden() {
var rowLetters = ["a", "b", "c", "d", "e", "f", "g", "h", "i"];
for(var i = 0; i < rowLetters.length; i++) {
var hiddenRow = document.getElementById(rowLetters[i] + "_row");
for(var j = 1; j < 10; j++) {
if(j == 1) {
hiddenRow.value = document.getElementById(rowLetters[i] + j).value + ",";
continue;
} else if(j != 9) {
hiddenRow.value += document.getElementById(rowLetters[i] + j).value + ",";
continue;
} else {
hiddenRow.value += document.getElementById(rowLetters[i] + j).value;
}
}
}
document.getElementById("mainForm").submit();
}
window.onload = function() {
initGrid();
}
</script>
<style>
.sudokuCells
{
width: 15px;
}
#valid
{
color: #00FF00;
visibility: hidden;
}
#invalid
{
color: #FF0000;
visibility: hidden;
}
</style>
</head>
<body>
<div id = "mainTableContainer">
<table border = "1" cellpadding = "0" cellspacing = "0" id = "mainTable">
<thead>
<tr>
<th></th>
<th>a</th>
<th>b</th>
<th>c</th>
<th>d</th>
<th>e</th>
<th>f</th>
<th>g</th>
<th>h</th>
<th>i</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<div id = "statusContainer">
<p><strong><span id = "valid">Valid</span> <span id = "invalid">Invalid</span></strong></p>
</div>
<form action = "evaluate.php" method = "post" id = "mainForm" >
<input type = "hidden" name = "a_row" id = "a_row" value = "" />
<input type = "hidden" name = "b_row" id = "b_row" value = "" />
<input type = "hidden" name = "c_row" id = "c_row" value = "" />
<input type = "hidden" name = "d_row" id = "d_row" value = "" />
<input type = "hidden" name = "e_row" id = "e_row" value = "" />
<input type = "hidden" name = "f_row" id = "f_row" value = "" />
<input type = "hidden" name = "g_row" id = "g_row" value = "" />
<input type = "hidden" name = "h_row" id = "h_row" value = "" />
<input type = "hidden" name = "i_row" id = "i_row" value = "" />
</form>
<button type = "button" onClick = "populateAllHidden()" >Evaluate!</button>
</body>

Categories

Resources