How to change answer buttons after clicking on "Add" button? - php

I have an application [here][1] where an user is able to select their options and answers. Please follow steps below in application.
Step 1: When you open application, you will see the "Open Grid" link,
click on it and select an option type, after you select an option it
will display the answer buttons at the bottom. For example if the
option you choose is "5", it will display 5 answer buttons "A - E",
if option chose is 8, it will display 8 answer buttons "A-H".
Now this is fine. As you can see the correct amount of answer buttons appear depending on the option chosen from the grid. But the problem I have is if the user wants to add a previous option. please look at steps below:
Step 2: You will see a green plus button on left hand side, click on
it, this will open up a modal window.
Step 3: In the search box type in "AAA" and then click on "Submit"
button, it will display rows from the database.
Step 4: If you look at the first row you can see that under "Option Type" column, it is A-D. Select this row by clicking on the "Add" button.
What will happen is that the
modal window will close and if you look at the answer and option
control on the right hand side, you can see that the Option Type
textbox contains the number 4 (This is because Option Type was "A-D" so there are 4 options "A,B,C,D"), so it should display answer buttons A-D but it doesn't, it doesn't change the answer buttons at all, they remain the same.
So my question is how can I get the correct Answer buttons to appear after the user has clicked on the "Add" button?
Below is the code where it imports the answer buttons after an option is selected from the grid:
$('.gridBtns').on('click', function()
{
var clickedNumber = this.value;
$(this).closest('.option').siblings('.answer').find('.answers').each(function(index) {
if (!isNaN(clickedNumber) && index < clickedNumber) {
$(this).show();
} else {
$(this).hide();
$(this).removeClass('answerBtnsOn');
$(this).addClass('answerBtnsOff');
}
var $this = $(this);
var context = $this.parents('.optionAndAnswer');
console.log($this);
});
if (clickedNumber === 'True or False') {
$(this).closest('.option').siblings('.answer').find('input[name=answerTrueName]').show();
$(this).closest('.option').siblings('.answer').find('input[name=answerFalseName]').show();
} else if (clickedNumber === 'Yes or No') {
$(this).closest('.option').siblings('.answer').find('input[name=answerYesName]').show();
$(this).closest('.option').siblings('.answer').find('input[name=answerNoName]').show();
}
getButtons();
});
});
function getButtons()
{
var i;
if (initClick == 0) {
for (i = 65; i <= 90; i++) { // iterate over character codes for A to Z
$("#answer" + String.fromCharCode(i)).removeClass("answerBtnsOn").addClass("answerBtnsOff");
}
initClick = 1;
}
// code above makes sure all buttons start off with class answerBtnsOff, (so all button are white).
}
Below is function where it controls what happens after the "Add" button has been clicked on:
function addwindow(numberAnswer,gridValues) {
if(window.console) console.log();
if($(plusbutton_clicked).attr('id')=='mainPlusbutton') {
$('#mainNumberAnswerTxt').val(numberAnswer);
$('#mainGridTxt').val(gridValues);
} else {
$(plusbutton_clicked).closest('tr').find('input.numberAnswerTxtRow').val(numberAnswer);
$(plusbutton_clicked).closest('tr').find('input.gridTxtRow').val(gridValues);
}
$.modal.close();
return false;
}

After analyzing your above code as well as HTML source code of link you gave, looks like you are just one step behind. You are only assigning the grid value(4 in above case) to in mainGridTxt input box. You need to trigger the click event on the grid buttons.
Put the below code after $model.close
$('#btn'+gridValues).trigger('click');
Above code will trigger the click event on grid button with id 'btn4'.

Related

jQuery $.post affecting multiple rows in table after a previous accidental click

I have a web page that allows authorized users to update or delete rows in a MySQL table. The table has the columns id (INT), label (VARCHAR), details (VARCHAR), templateId (INT), and auditable (TINYINT, either 0 or 1). This table is displayed as HTML on the front end, with "Label", "Details", "Auditable?" and "Edit/Delete" columns showing.
Clicking the "Edit" button on a row, changing some data in the resulting Bootstrap modal form, and clicking "Save Changes" works fine. The problem occurs when I click "Edit", click "Cancel" on the form, and then click another row (say, for example, I accidentally clicked the wrong row). When I click the button to execute the edit on that newly clicked row, both that row and the initially clicked row will be affected. The Chrome console shows that two JavaScript objects are being sent via $.post(), though I cannot figure out why from the logic I wrote (see below). I looked in MySQL and the duplicate results are there, confirming the page accurately reflects the update. Is there some $.get or $.post cache behavior in jQuery I am not aware of? (This also occurs with the delete functionality, but I'm limiting the question for brevity's sake).
Main page (GUI):
// The 'edit this row' button that brings up the modal form
$(".edit-action").click(function() {
// Clear any previously set values in form
$("#editActionLabel").val('');
$("#editActionDetails").val('');
$(".radio-edit-action").prop("checked", false);
// All edit button id's in GUI table will be "edit-action-[`id` in database]"
// Grab number out of there and convert from string to number
var actionId = $(this).attr("id");
actionId = parseInt(actionId.slice(12));
// Grab data from database to populate fields
$.get("data.php?a=actionData&actionId=" + actionId, function(d) {
// Returning a JSON encoded array isn't working,
// so I'm sending back a comma-separated string instead
var response = d.split(",");
var label = response[0];
var details = response[1];
var auditable = parseInt(response[2]);
$("#editActionLabel").val(label);
$("#editActionDetails").val(details);
if (auditable == 1) {
$("#editAuditableNo").prop("checked", false);
$("#editAuditableYes").prop("checked", true);
} else if (auditable == 0) {
$("#editAuditableYes").prop("checked", false);
$("#editAuditableNo").prop("checked", true);
}
// Only reset `auditable` variable if selection was changed
$(".radio-edit-action").change(function() {
auditable = $(this).val();
auditable = parseInt(auditable);
});
// User clicks "Save Changes" instead of "Cancel"
$("#executeEdit").click(function() {
var label = $("#editActionLabel").val();
var details = $("#editActionDetails").val();
var obj = {
"operation": "edit",
"actionId": actionId,
"label": label,
"details": details,
"auditable": auditable
};
console.log("The object passed to 'edit' this row:");
console.log(obj);
$.post("data.php", obj, function(r) {
// Confirm success or failure to user
$("#crudResult").html(r);
});
}); // end click
});
}); // end 'edit action'
data.php (called via AJAX to execute the UPDATE in database. Only relevant code shown):
$debug = false;
$operation = $_POST['operation'];
$action_id = (isset($_POST['actionId']) ? $_POST['actionId'] : '');
$label = (isset($_POST['label']) ? $_POST['label'] : 'NULL');
$details = (isset($_POST['details']) ? $_POST['details'] : 'NULL');
$auditable = (isset($_POST['auditable']) ? $_POST['auditable'] : 'NULL');
switch ($operation) {
case 'edit':
$query = "
UPDATE actions
SET label='$label',
details='$details',
auditable=$auditable
WHERE id=$action_id
LIMIT 1";
// DB connection not shown. Yes, I know I should be using PDO...
$result = mysqli_query($db_conn, $query);
// PHP echoes out the result; let the calling JavaScript figure out where to place it
if ($result) {
echo '<p class="text-success">Action successfully updated!</p>';
} else {
echo '<p class="text-warning">There was an error and the action could not be edited.</p>';
// Don't show error to user in production, when $debug should be false
if ($debug) {
echo '<p><b>Error:</b> ' . mysqli_error($db_conn) . '</p>';
}
}
break;
/* case 'delete': ... */
}
The modal form, which follows Bootstrap's template HTML, is simply a collection of fields and a couple buttons (no <form> wrapped around it). Please let me know if I can clarify anything.
How many times is the request to server occurs? I Bet it is twice.
The problem is on the client side.
For each edit click you have made, a new save click function has been created.
You do not need to add this for every edit click, take it out from the edit click function.
Hope it helps.

how to turn on multiple buttons?

Got a bunch of letter buttons in code below:
<?php
$a = range("A","Z");
?>
<table id="answerSection">
<tr>
<?php
$i = 1;
foreach($a as $key => $val){
if($i%7 == 1) echo"<tr><td>";
echo"<input type=\"button\" onclick=\"btnclick(this);\" value=\"$val\" id=\"answer".$val."\" name=\"answer".$val."Name\" class=\"answerBtns answers answerBtnsOff\">";
if($i%7 == 0) echo"</td></tr>";
$i++;
}
?>
</tr>
</table>
Now the code below is able to turn on an answer button:
$('#answer'+btn).addClass("answerBtnsOn");
Below is code for when "Add" button is clicked, it retrieves the "Answer" from the column:
echo '<td class="answertd">'.htmlspecialchars($searchAnswer[$key]).'</td>';
echo "<td class='addtd'><button type='button' class='add' onclick=\"parent.addwindow('$searchAnswer[$key]');\">Add</button></td></tr>";
Below is the code where for each button (btn), it turns on/off the buttons:
function btnclick(btn)
{
if ($(btn).hasClass("answerBtnsOn")) {
$(btn).removeClass("answerBtnsOn").addClass("answerBtnsOff");
return false;
}
if ($(btn).hasClass("answerBtnsOff")) {
$(btn).removeClass("answerBtnsOff").addClass("answerBtnsOn");
return false;
}
}
But the only problem is that the code above is only able to turn on a single answer button on only. For example if the "Answer" is B, then it will turn answer button B on which is fine, or if the "Answer" is E, it is able to turn answer button E on.
The problem is that if there are multiple answers. If the "Answer" is B E, then it does not turn on buttons B and E, if "Answer" is A D F, it doesn't turn on buttons A D and F.
So my question is that how can I turn on multiple buttons if there are multiple Answers?
DEMO:
click here to view the demo and please follow the steps so you can use the demo:
Step 1: When you open applicaton, you see a green plus button on the
page, click on it and it will display a modal window.
Step 2: In modal window there is a search bar, type in "AAA" and
submit search, you will see a bunch of rows appear.
Step 3: In the first row, you see under "Answer" colum that the
answer is B, click on the "Add" button within this row, the modal
window will close and you will see that the answer buttons have been
displayed with the "B" button highlighted.
Now this works fine but it only works for single answer, follow the steps below:
Step 4: Click on the green plus button again and perform the same
search for "AAA";
Step 5: This time select a row which has multiple answers under the
"Answer" column e.g the third row has answer "A C" under the "Answer"
column. Add this row by clicking on "Add" button
Step 6: You will see that it displays the relevant buttons but it
doesn't turn on any of the answer buttons, "A" button and "C" button
are not highlighted green. This is the problem I am having
UPDATE:
//I can't use the toggle method you have mentioned because there is a suitable reason for this (long story)
if ($(btn).hasClass("answerBtnsOn")) {
$(btn).removeClass("answerBtnsOn").addClass("answerBtnsOff");
return false;
}
if ($(btn).hasClass("answerBtnsOff")) {
$(btn).removeClass("answerBtnsOff").addClass("answerBtnsOn");
return false;
}
//When "Add" button is clicked, it should turn on correct buttons
function addwindow(condition) {
$('input[type=button]').each(function(){
if (condition){
$(this).addClass('correct');
}
});
}
HTML code is same as html code on top of question
You need to use class instead of ID and give the same class to all correct answers, so all correct answers will get class of .correct and then in jquery:
$('.correct').addClass("answerBtnsOn");
EDIT:
Answering your question in the comment - yes, you should create an array of the buttons, run on it and add the .correct class to all the right answers.
Also change you code from:
if ($(btn).hasClass("answerBtnsOn")) {
$(btn).removeClass("answerBtnsOn").addClass("answerBtnsOff");
return false;
}
if ($(btn).hasClass("answerBtnsOff")) {
$(btn).removeClass("answerBtnsOff").addClass("answerBtnsOn");
return false;
}
To:
$(btn).toggleClass("answerBtnsOn");
$(btn).toggleClass("answerBtnsOff");
It should do the same with much less code.
EDIT2:
The loop would be something like this:
$('input[type=button]').each(function(){
if (condition){
$(this).addClass('correct'));
}
});
where condition is true if this answer is correct.
Here is the modified code. At first we initialize php variables:
$a = range("A","Z");
$correct = "ADERW"; // some string with correct letters (aka answers)
Now we place the javascript function into page's head (or to an external file):
var oanswers = new Object(); // this object's attributes are named as correct letters
var answers = '<?php echo $correct; ?>'; //string
for (var i=0; i<answers.length; i++) {
oanswers[answers[i]] = true;
}
function btnclick(btn) {
if (!oanswers.hasOwnProperty(btn.id[6])) {
return;
}
if ($(btn).hasClass('answerBtnsOff')) {
$('.answers').each(function(){ // turn all correct answers on
if (oanswers.hasOwnProperty(this.id[6])) {
$(this).addClass('answerBtnsOn');
$(this).removeClass('answerBtnsOff');
}
});
} else {
$('.answers').each(function(){ // turn all correct answers off again
if (oanswers.hasOwnProperty(this.id[6])) {
$(this).addClass('answerBtnsOff');
$(this).removeClass('answerBtnsOn');
}
});
}
}
The btnclick function can toggle all correct answers Off and On. If you don't want toggling, simply erase the whole else branch. Instead of testing presence of the .created class, now it tests whether the object's property is defined or not.

Allow Users to Select Multiple Options, Aggregate Results and Display

I am having difficulty finding specifically what I'm searching for, most likely because I'm not sure how to express it well in a Google search.
Basically what I would like to do is display 30 or so buttons that users would then be able to select. Once selected a button changes color indicating that the particular option has been chosen. Users are required to select 10 out of 30 options. The results should then be aggregated (basically counting each unique button selected) and displayed to another user who can login and see the results.
Multiple users should be able to select these options and have their results recorded.
I'm not looking to create a drop down list, multi-list, or checkbox solution. In my research so far I have found plenty of references to this type of option. Also, Javascript restricting the min/max number of checkboxes a user can select.
I hope that makes sense. Any assistance with identifying the best method for going about this task would be greatly appreciated.
Thank You,
-Nathan
What you can do, you can create 30 buttons, and connect each button to a hidden check box, then you can post it to server, eg.
<input type="checkbox" value="1" name="chk_one" id="chk_one" style="display: none;">
<input type="button" value="Check Box One" id="btn_one"/>
CSS
input[type="button"].selected { color: red; }
input[type="button"] { color: black; }
then you can write jQuery solution in order to make it change colors:
var _minLength = 10;
var _maxLength = 30;
$(document).ready(function() {
$('#submit_id').click(function() {
if($('#form_id input[type="checkbox"]').is(':checked').length < _minLength)
{
alert('you need to select at least ' + _minLength + ' of buttons'); return false;
};});
$('#form_id input [type="button"]').click(function() {
var _id = $(this).attr('id').toString().split('_')[1];
if(_id != null)
{
var _chckBox = $('#chk_'+_id);
var _newState = _checkBox.attr('checked') ? false, true;
if($('#form_id input[type="checkbox"]').is(':checked').length+1 > _maxLength)
return;
_checkBox.attr('checked', _newState);
if(_checkBox.attr('checked'))
$(this).addClass('selected');
else
$(this).removeClass('selected');
}
});
});
Method from above will attach click event to every button in the area you specified with "#form_id" then when clicked it will toogle state of hidden checkbox and will set or remove class from button, it depends of checkbox state.
And by the way number of checkboxes is not limited.

Store checked values from ajax pages

Mostly i have 28 items, i used pagination and display in 3pages using Ajax
each page have 10 items, whatever i selected in check box it should display values at bottom ,every thing is OK right now, but my problem is when i select items in second page the previous list is disappearing , when i return back to fist page it is not showing previously selected items .
iam not getting how to do this
please help
thanks
i used this jquery code to get checked values
function showValues() {
var page = $("#pagedis").val();
var fields = $(":input").serializeArray();
$("#results_" + page).empty();
jQuery.each(fields, function(i, field) {
$("#results_" + page).append(field.value + "<br> ");
});
}
i need the action like gmail if we select 3 items in one page ,4 items in 2nd page ,when i come back the checked value will never chage
do your checkboxes all have the same name? If not, name them all the same.
make sure each checkbox has a unique value attribute
attach a handler to keep track of the checkboxes checked in an array
:
// global variable somewhere
var checkedBoxes = new Array();
$('input[name=theNameYouDefinedAbove]').click(function(event){
checkedBoxes[$(this).val()] = $(this).is(':checked');
});
Now, when you paginate, just do this
:
$('input[name=theNameYouDefinedAbove]').each(function(index, checkbox){
if (checkedBoxes[$(checkbox).val()]) {
// NOTE: choose ONLY ONE!
// for jQuery 1.6+
$(checkbox).prop('checked', true);
// for all jQuery
$(checkbox).attr('checked', 'checked');
}
});

jquery skip a block

I have a jquery game that you can view here link text
The game starts by you entering a number in a text field.
then you click the play button.
After clicking the play button a set of square appear each rotating random numbers, click on the square that has your number to build up your score, miss 3 times and you are done.
I added the game to my site, you can view it here link text
the problem I'm having is that my site members will just keep the cursor on one box and wait for their number to appear in that one box. Which ruins the game.
Is there a way to make it so they can't click on the same box more than once in a row. They'll have to go click another box before they can come back to this one.
here's my complete script
var hitCount = 0,
missCount = 0;
function IsNumeric(n) {
return !isNaN(n);
}
$("#getit").click(function() {
var hitCount = 0,
missCount = 0;
$('#hitcount').text(0);
$('#misscount').text(0);
$('#message').hide(100);
var li = [],
intervals = 0,
n = parseInt($('#MyNumber').val());
var intervalId = -1;
if (IsNumeric(n)) {
intervalId = setInterval(function() {
li[intervals++ % li.length].text(Math.random() > .1 ? Math.floor(Math.random() * (10 + n) + (n / 2)) : n).attr('class', '') ;
}, <?php echo $time ?>);
}
$('#randomnumber').empty();
for (var i = 0; i < 7; i++) {
li.push($('<li />').appendTo('#randomnumber'));
}
$('#randomnumber').delegate("li", "click", function() {
var $this = $(this);
if (!$this.hasClass('clicked')) {
if (parseInt($this.text(), 10) === n) {
$this.addClass('correct');
$('#hitcount').text(++hitCount);
} else {
$this.addClass('wrong');
$('#misscount').text(++missCount);
}
//New code If the missCount > 3 stop the game and save the value
if(missCount>=<?php echo $limit ?>){
clearInterval(intervalId);
$('#randomnumber').undelegate("li", "click");
// Use a ajax request to save the values
$.ajax({
type : 'POST',
url : 'FBhighscore_hwnd.php',
dataType : 'json',
data: {
tgameid: $('#tgameid').val(),MyNumber: $('#MyNumber').val(),totalHits: hitCount
},
success : function(data){
$('#waiting').hide(500);
$('#message').removeClass().addClass((data.error === true) ? 'error' : 'success')
.text(data.msg).show(500);
if (data.error === true)
$('#loginForm').show(500);
else
$('#send').hide(500);
},
error : function(XMLHttpRequest, textStatus, errorThrown) {
$('#waiting').hide(500);
$('#message').removeClass().addClass('error')
.text('There was an error.').show(500);
$('#loginForm').show(500);
}
});
}
}
$this.addClass('clicked');
});
return false;
});
Have you tried using .one() to bind your click events, instead of .click()? Here's the documentation for it: http://api.jquery.com/one/
If you bind the click event with .one() then you could ensure that the function will only be triggered once. Then, inside that function, rebind the events for all other boxes, thus ensuring that they have to click another box before click the same one again.
Alternately:
Use a combination of .hover() and setTimeout() (and possibly hoverIntent) to disable a box when the user hovers their mouse over it for too long.
EDIT
Have a look at this modified version of your jsFiddle: http://jsfiddle.net/Ender/9ffTA/
Clicking on the same box twice in a row is disallowed. Hopefully you can use that as a guide.
Inside of your click you can mark that box as "locked" and just disable it until the next click.
That will not solve your problem. The user can still just move to another box and wait for their number to appear in that box. I just did it myself on your site. I don't believe there is a solution to your problem with the current game design.
I don't think the problem is with clicking, but with scoring.
Your proposed solution doesn't really defeat "waiting" as a strategy, as Drew points out. To really fix waiting, you need to give it a penalty.
Were it my game, I'd have three scoring metrics — correctly clicked boxes (what you're currently calling "hits"), incorrectly clicked boxes (... "misses"), and unclicked boxes (not in your current game). In other words, if my number is 5 and a box containing a 5 fades (is replaced by another number) before I click it, that's counted against me.
With this scoring system in place, anyone who simply hovers over a box and waits — even if they switch boxes between clicks — will watch their score get lower and lower as they miss boxes.

Categories