jQuery AJAX Button Click - Remove Table Row after AJAX Call is Successful - javascript

I'm displaying an HTML table and would like to include a button in the last column that, when clicked, performs an AJAX call which will result in the removal of the table row from the table. I'm new to jQuery and AJAX and working things out as I go - I've managed to setup some AJAX calls that run when a field is edited, but now I'm struggling to attach one to a button in a table row.
Here's how the table looks:
<tr class="" id="tableRow1"><td>Store 1</td><td>lorem ipsum</td><td>John Smith</td><td>20/11/2014 12:53:52 AM</td><td><button type="button" id="closeNote" class="btn btn-primary">Acknowledge</button></td></tr>
<tr class="" id="tableRow2"><td>Store 2</td><td>lorem ipsum</td><td>Sally Jones</td><td>20/11/2014 12:53:52 AM</td><td><button type="button" id="closeNote" class="btn btn-primary">Acknowledge</button></td></tr>
<tr class="" id="tableRow3"><td>Store 3</td><td>lorem ipsum </td><td>Bill Howden</td><td>12/11/2014 01:43:03 PM</td><td><button type="button" id="closeNote" class="btn btn-primary">Acknowledge</button></td></tr>
I know that the ID for the button is not unique - at the moment the script only fires when the button in the first row is clicked. I'm not sure how to assign a unique ID for each button which the script can see.
Here's my script:
<script type="text/javascript">
$(document).ready(function() {
$("#closeNote").click(function(){
$.post('editNote.php', { type: 'hideNote', id: '1E1DDA14-D2C6-4FC8-BA5F-DBCCC7ABAF7F' }, function(data) {
data = JSON.parse(data);
if (data.error) {
$("#ajaxAlert").addClass("alert alert-danger").html(data.text);
$("#ajaxAlert").show();
return; // stop executing this function any further
} else {
$("#ajaxAlert").hide();
$(this).closest('tr').remove();
}
}).fail(function (xhr) {
// no data available in this context
$("#ajaxAlert").addClass("alert alert-danger");
//display AJAX error details
$("#ajaxAlert").html(xhr.responseText);
$("#ajaxAlert").show();
});
});
});
</script>
I just need some help in bring this altogether so that when the button is clicked on any row it calls the script which in turn, if the PHP script it then calls is successful, it then removes the row where the button was clicked.

Rather than applying the button to an ID give each link a class:
<button class="btn btn-primary close-note"
Then amend your JS as follows:
$("button.close-note").click(function(){
Inside your callback functions the keyword this no longer refers to the element, but instead refers to the XHR object.
To solve this assign $(this) to a variable outside of the $.post
var $self = $(this);
$.post( ... ... function(response){
// code and stuff
$self.closest('tr').hide();
});
You also need to ensure that the browser doesn't then follow the link; amend the click line again:
.click(function(e){
e.preventDefault();

Related

aJax update a specific row in sqlite and php using a button

I've got a table that lists values inputted by a user, with 2 buttons on the side to remove or to mark completed. On the page the table is visable, there are 3 tabs, we will call these Tab1, Tab2, and Tab3
Each tab has a table (As described above) with information about a specific type of entry.
These buttons are simple <a href> links, so when clicked they reload the page. This is a problem because the users view is refreshed and it takes the tabs back to the default tab, and is also an inconvenience when trying to mark several entries.
I would like to make these buttons send Ajax requests to another page to process the data. The only problem is, I am not really sure how to make the ajax call.
This is what I have right now
My buttons
echo "<td class='td-actions'>";
echo " <a href='?complete=".$row['uniqueID']."' class='btn btn-success btn-small'>
<i class='btn-fa fa-only fa fa-check'> </i>
</a>
<a href='?remove=".$row['uniqueID']."' class='btn btn-danger btn-small'>
<i class='btn-fa fa-only fa fa-remove'> </i>
</a>";
echo "</td>";
There is one called Complete, and one called Remove.
When either of these are pressed, it currently reloads the page which triggers a few php if statements.
if(isSet($_GET['remove'])) {
$sql = "DELETE from rl_logged where uniqueID='".$_GET['remove']."';";
$ret = $db->exec($sql);
echo "<meta http-equiv='refresh' content='0;index.php' />";
}
if(isSet($_GET['complete'])) {
$sql = "UPDATE rl_logged set complete=1 where uniqueID='".$_GET['complete']."';";
$ret = $db->exec($sql);
echo "<meta http-equiv='refresh' content='0;index.php' />";
}
These are relatively simple functions. My problem is that I do not know javascript very well.
Any help would be much appreciated.
the javascript that I have come up with is this
$(document).ready(function() {
$('#markComplete').click(function() {
var input = input = $(this).text()
$.ajax({ // create an AJAX call...
data: {
onionID: input,
},
type: 'POST', // GET or POST from the form
url: 'pages/ajax/markCompleteRL.php', // the file to call from the form
success: function(response) { // on success..
refreshAllTabsWithFade();
}
});
});
});
using this button
<div name='markComplete' id='markComplete' class='btn btn-success btn-small'>
<i class='btn-fa fa-only fa fa-check'></i>".$row['uniqueID']."
</div>
But, while inspecting with firebug, this seemed to work ONCE, but now the button doesn't do anything.
I tried again this morning, the button presses and the first time it sends this post, then the button doesn't do it again - even on page reload.
I was able to get it to work with the following:
javascript:
$('.markComplete').submit( function( event ) {
event.preventDefault();
event.stopImmediatePropagation();
$.ajax({ // create an AJAX call...
data: $(this).serialize(), // serialize the form
type: "POST", // GET or POST from the form
url: "pages/ajax/repairlogMarks.php", // the file to call from the form
success: function(response) { // on success..
refreshAllTabs();
}
});
return false;
});
button:
<form class="markComplete">
<input type="text" style="display:none;" class="form-control" name="uniqueid" value='<?=$row['uniqueID'];?>'>
<input type="text" style="display:none;" class="form-control" name="markcomp" value='1'>
<button type="submit" class="btn btn-success">
<i class="btn-fa fa-only fa fa-check"></i>
</button>
</form>
Basically, I made the button into a form which I knew how to create an ajax request for.
--
Update to make it work for multiple buttons that do the same function for different unique ID's.
Well for since you're sending the ajax call using "POST", it seems to me that if(isSet($_GET['complete'])) would evaluate to false. Also if your button is generated dynamically using php then change your click handler to the following:
$('document').on('click', '#markComplete', function (){
// Your code here
})
If you have more than one "Mark Complete" button; you need to use classes rather than ID to bind the event.
<button id="test">
Test 1
</button>
<button id="test">
Test 2
</button>
<script>
$('#test').click(function (e) {
console.log('test', e.target);
});
</script>
In this example, only the first button works. jQuery will only return the first element when you specify an ID.
If you use classes to bind the event; both buttons will work:
<button class="test">
Test 1
</button>
<button class="test">
Test 2
</button>
<script>
$('.test').click(function (e) {
console.log('test', e.target);
});
</script>
i think you have an error in your javascript at this line...
var input = input = $(this).text()
try to replace by this..
var input = $(this).text();

JSP/Struts2: how to access object bean in selected table row

In my Struts2 application, I have a table that is dynamically populated with data, coming from the database (via Eclipselink JPA). Below that table there's a button that became enabled as soon as a row is selected in the table (jQuery). Now, when that button is clicked, I need to know which row is currently selected, so I can access the corresponding object bean, since I need to pass the bean ID (target_id) into the next page (createexperiment2 action). So, in short, the question is: How can I access the Struts2 object bean that is contained in the selected (clicked) table row?
1. Screenshots:
Before row selection -> After row selection
2. JSP code:
<table id="targets" class="ink-table grey tableSection">
<thead>
<tr>
<th colspan="5" class="align-left">Select your target:</th>
</tr>
</thead>
<tbody>
<s:if test="targets.size > 0">
<s:iterator value="targets">
<tr id="row_<s:property value="i"/>">
<td class="all-100"><s:param name="id"><s:property value="target_id"/></s:param></s:url>"><s:property value="name"/></td>
<td class="all-15"><s:param name="id"><s:property value="target_id"/></s:param></s:url>">edit</td>
<td class="all-5">|</td>
<td class="all-15"><s:param name="id"><s:property value="target_id"/></s:param></s:url>">delete</td>
<td class="all-5">?</td>
</tr>
</s:iterator>
</s:if>
</tbody>
</table>
[...]
<a href="createexperiment2" class="ink-button double-vertical-space all-25 buttonSection" id="next" disabled>Next ></a>
3. jQuery code:
$(document).ready(function(){
$('.tableSection tbody tr').click(function()
{
var selected = $(this).hasClass("highlight");
$('.tableSection tbody tr').removeClass("highlight");
$('.buttonSection').attr("disabled", false);
if(!selected)
$(this).addClass("highlight");
});
});
EDIT 1:
With the help of Andrea, I've finally been able to access Struts2 functions with jQuery, the poblem is that I can only access the properties of the last bean on the table (the last one that was accessed when the JSP was rendered, which makes sense). See the updated code below, while I'll try a workaround for this:
JSP:
<s:if test="targets.size > 0">
<s:iterator value="targets">
<tr onclick="<s:set var="tid" value="target_id"/>">
[...]
</tr>
</s:iterator>
</s:if>
[...]
<script type="text/javascript">
$(function () {
$('.tableSection tbody tr').click(function(event) {
alert ('<s:property value="%{#tid}" />');
});
});
</script>
EDIT 2:
Now I know which table row index has been clicked, but after hours of trying to assign it to a variable (using Struts tags) and send it to the action, I'm still not getting what I want. I'm not even being able to send this row index to the Action. This is frustrating. Nevertheless, that's how I got to know which row has been selected:
<tr onclick="getRow(this)">
[...]
<script>
function getRow(x)
{
alert("Selected row: "+x.rowIndex);
//return x.rowIndex;
}
</script>
EDIT 3:
This time, I was finally able to send the row ID (a String), to the action. The only remaining issue is that the action gets call twice, the first one on the click event, and the other one because of the href attribute of the a HTML element, which redirects to the desired Struts2 action. Apart of being obviously inneficient, this naturally makes the variable become null on the second call to the action. Do you know how can I somehwow "merge" this 2 calls to the createxperiment2 action into only one? I've tried with the async option in the AJAX call set to false, with no success.
[first, removed the onclick event from the table tr, since I only need to know which row is highlighted when the "Next" button is pressed]. The code currently goes like this:
<script type="text/javascript">
$('#next').click(function(event)
{
var row = $('.highlight').index();
alert (row);
$.ajax({
method: "POST",
url: "createexperiment2.action",
data: { row : row }
});
});
</script>
Q: I have assigned an ID to each table row. How can I know which one is the selected one?
Obtain the object's id with the this keyword:
$('.tableSection tbody tr').click(function(event) {
alert (this.id);
...
Q: how can I use the selected table row ID to access the corresponding bean object (represented in the row itself)?
This is not clear: just submit your id and retrieve the object serverside, no matter if through AJAX or a standard form submit.
Finally, the solution:
First get the ID of the object (I made it with Struts). Then, with the help of an AJAX call, send the ID to the desired action (url: attribute). Upon success of this action, define with the success: callback option where you want to redirect it.
Struts / JSP:
<s:if test="targets.size > 0">
<s:iterator value="targets">
<tr id="<s:property value="target_id"/>" class="highlight">
[...]
</tr>
</s:iterator>
</s:if>
jQuery:
<script type="text/javascript">
$('#next').click(function(event)
{
var tid = $('.highlight').attr("id");
$.ajax({
method: "POST",
url: "createexperiment2.action",
data: { tid : tid },
success:
function()
{
//alert("TID -> "+tid);
window.location = "loadworkloads.action";
}
});
});
</script>

Can't click button more than one time when append html data

I've a problem with jquery. I use ajax to send id to delete from DB and then return html file to update content without reload page (I use struts 2) , first time run or reload page my button work fine ( row was deleted and my content was updated) but when I try to click button again , it doesn't respond.
My script
$(document).ready(function() {
$(".btnEdit").click(function() {
alert("Edit");
});
$(".btnDelete").click(function() {
id = $(this).attr('id');
alert("Delete ID : " + id);
$.ajax({
url: "delete",
type: 'POST',
data: {'id': id},
cache: false,
success: function(data, textStatus, jqXHR) {
$('.catagoryContent').remove();
$('.container').append(data);
},
error: function(jqXHR, textStatus, errorThrown) {
alert("error");
}
});
});
});
Sorry, I forgot return data code.
<div class="catagoryContent">
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Edit / Delete</th>
</tr>
</thead>
<tbody>
<s:iterator value="catagoryList" var="catagory">
<tr>
<td>${catagory.id}</td>
<td>${catagory.name}</td>
<td>
<button class="btn btn-primary btnEdit" id="${catagory.id}">Edit</button>
<button class="btn btn-warning btnDelete" id="${catagory.id}">Delete</button>
</td>
</tr>
</s:iterator>
</tbody>
</table>
At document ready you initialize all tags with class "btnDelete" to the click function.
When you do a successfully ajax call, you replace all your content with response from the server.
At that point you remove all your buttons and add new data with new buttons.
jQuery is not listening to these buttons because the $(".btnDelete").click(... was only set at page load.
if you change
$(".btnDelete").click(function() {
to
$(document).on("click", ".btnDelete", function() {
it will still work after you add new data to .container
The "on" function also triggers when you dynamically add new tags with class ".btnDelete" (See here)
You aren't listening to the click event on your updated html.
You should use
$list.on('click', '.btnEdit', function() { ... })
where $list is the element containing the items (probably a <ul>)
This is because click event handler is attached at the page startup.
But when you reload the part of your page, old button with onclick handler is being removed.
The decision is to use
$(document.body).delegate('.btnDelete', 'click', function(){...})
instead of
$(".btnDelete").click(function(){...})
This way you will attach event handler to body element (which will fire always), and jQuery will check whether the clicked element has class .btnDelete, or not.
So it will work even if you delete these buttons and then insert new ones.
Another approach is to attach onclick handlers to the buttons every time they created, but I think the first approach is easier

Delete Record Confirmation Message

I wonder whether someone may be able to help me please.
Firstly, my apologies because I'm really very new to this, so please forgive me what some may seem a very basic question/error.
The extract of code below, successfully creates a table of records pertinent to the current user.
Working Solution - Baylor Rae' worked tirelessly with me over the last 3-4 days to find a solution. All Baylor Rae' was unable to provide a fully successful script, they certainly helped considerably in moving this on . However the full working script below is Courtesy of jazzman1 # PHP Freaks
Main Script
<script type="text/javascript">
$(document).ready(function(){
$('form.delete').submit(function(e){
console.log('submit'); return false;
})
})
</script>
<script type="text/javascript">
$(document).ready(function(){
$('form.delete').submit(function(e){
e.preventDefault();
var elem = $(this).closest('.delete');
var lid = $(this).serialize();
$.confirm({
'title' : 'Delete Confirmation',
'message' : 'You are about to delete this Location. <br />It cannot be restored at a later time! Do you wish to continue?',
'buttons' : {
'Yes' : {
'class' : 'blue',
'action': function(){
//elem.slideUp();
$.ajax({
url: 'deletelocation.php',
type: 'POST',
data: lid,
success: function(response) {
console.log('success', response);
},
error: function() {
console.log('error')
}
});
}
},
'No' : {
'class' : 'gray',
'action': function(){} // Nothing to do in this case. You can as well omit the action property.
}
}
});
});
})
</script>
jqueryconfim.js
(function($){
$.confirm = function(params){
if($('#confirmOverlay').length){
// A confirm is already shown on the page:
return false;
}
var buttonHTML = '';
$.each(params.buttons,function(name,obj){
// Generating the markup for the buttons:
buttonHTML += ''+name+'<span></span>';
if(!obj.action){
obj.action = function(){};
}
});
var markup = [
'<div id="confirmOverlay">',
'<div id="confirmBox">',
'<h1>',params.title,'</h1>',
'<p>',params.message,'</p>',
'<div id="confirmButtons">',
buttonHTML,
'</div></div></div>'
].join('');
$(markup).hide().appendTo('body').fadeIn();
var buttons = $('#confirmBox .button'),
i = 0;
$.each(params.buttons,function(name,obj){
buttons.eq(i++).click(function(){
// Calling the action attribute when a
// click occurs, and hiding the confirm.
obj.action();
$.confirm.hide();
return false;
});
});
}
$.confirm.hide = function(){
$('#confirmOverlay').fadeOut(function(){
$(this).remove();
});
}
})(jQuery);
Form In Main Script
<form name="delete" id="delete" class="delete">
<input type="hidden" name="lid" id="lid" value="<?php echo $theID ?>" />
<input type="submit" value="Delete Record"/>
</form>
deletelocation.php
<?php
$lid = intval($_POST['lid']);
$query = mysql_query("DELETE FROM table WHERE locationid='".$lid."'");
?>
You'll see that the end of the table are four buttons, which, through the locationsaction.php script navigate the user to four different screens all linked back to the main table record via the lid value. This script is shown below.
I'm now trying to implement a confirmation message for the Delete function. The source code for this can be found here.
This is where I've become a little unsure about what to do next. I've tried to link the button on click event with the name of the Delete function, but rather than the confirmation message, the user is taken to a blank screen and the record is deleted.
I've run the JavaScript Console and there are no errors created, so I'm a little unsure about how to continue.
I just wondered whether someone could possibly take a look at this please and let me know where I'm going wrong.
Many thanks and kind regards
Prevent the Redirection
It looks like you're getting the redirection because the form is still submitting. You need to prevent the form from submitting by adding the following line at the beginning of your click event.
$('#btn-delete').click(function(e) {
e.preventDefault();
var elem = $(this).closest('.item');
Calling e.preventDefault() will prevent the browser's default action from occuring, in this case submitting the form.
Changing the way buttons are handled
As far as I can tell locationsaction.php redirects to a page based on the value of the button.
A better way to do this would be to create a link to each page and pass the lid as a parameter. This is the standard way of linking pages while providing some context for the next page.
Note: You will need to change each page to use $_GET['lid'] instead of $_SESSION['lid'].
Note 2: It is perfectly valid to "close" and "open" PHP tags in the middle of a page. In the code I provided below I closed PHP so I could write HTML, and reopened PHP when I was done.
<?php // this line is for syntax highlighting
/* display row for each user */
$theID = $row['locationid'];
?>
<tr>
<td style="text-align: center"><?php echo $row['locationname'] ?></td>
<td>Images</td>
<td>Add Finds</td>
<td>View Finds</td>
<td>
<form method="post" action="deletelocation.php" class="delete-record">
<input type="hidden" name="lid" value="<?php echo $theID ?>" />
<input type="submit" value="Delete Record" />
</form>
</td>
</tr>
<?php
The only time I didn't use a link was when I linked to the deletelocation.php file. This is because you should never use a GET request when modifying a database.
Using a POST request is an easy way to prevent Cross-site Request Forgery.
Rename your table column names
I noticed that your column names for locationid and locationname didn't have any type of separation. I would recommend renaming these to location_id and location_name.
This applies to your file names as well. You can include an underscore or dash to separate the words in your filename. I usually use an underscore because I think it reads better, but it's your choice.
POST directly to the delete page
Because you're using AJAX, you can specify the deletelocation.php url directly. With the changes I've suggested above, there isn't a reason to keep locationsaction.php.
$.ajax({
url: 'deletelocation.php',
type: 'post',
data: $(this).parent().serialize(),
success: function () {
img.parent().fadeOut('slow');
}
});
I also changed how the data was passed. .serialize() will automatically grab the location id from input[name=lid] and create a query string like lid=1.
Edit #1
If possible, I'd like to keep the locationsaction script. A lot of my pages further down the line rely on a SESSION id, and using a Get isn't an option without re-writing a lot of code.
The way you're using locationsaction.php and sessions isn't the way I'd do it. But it's your application structure and you can build it however you like.
Could I change the button type to button rather than submit, keeping the id the same so the JS code will pick this up?
You can change the type to button, but when javascript is disabled it won't submit the form. In general, you write your page to work without JS, and then write the JS to modify the browser's default behavior.
Could you also confirm for me whether your AJAX just replaces the top section of my code?
No, I only changed the way you set the lid. You still need to include all the JS wrapped around it, I just didn't want to paste the whole block of code.
Observation 1:
function delete(){
$(document).ready(function(){
Is that really the order of the lines in your code? The jQuery ready hook lies INSIDE of your function definition? Or have you, by mistake, posted them here in the wrong order here.
If it's the former case, then please, fix this first before anything else. Otherwise, read on:
Why $('.item .delete')? I don't see any markup with class .item? Where is it? Are you sure that this selector matches some elements in the first place? Also, you should use #delete for referencing elements through their id attributes, not .delete, as that looks for elements with the class delete.
Your id:delete button and the other buttons are submit type buttons, which means that their click handlers simply will not block the submission flow. You can change all the button types to button, instead of having them as submit. Code example below.
Why the declarative onClick on the delete button? Get rid of it.
(Also, you really don't need a form in this case, unless you want to deserialize the form, which doesn't seem like a requirement or intent given your markup).
<td><input type='button' name='type' id='details' value='Details'/></td>
<td><input type='button' name='type' id='images' value='Images'/></td>
<td><input type='button' name='type' id='addFinds' value='Add Finds'/></td>
<td><input type='button' name='type' id='viewFinds' value='View Finds'/></td>
<td><input type='button' name='type' id='delete' value='Delete' /></td>
And your JS:
//please, be careful with the selector.
//it could be that it is not matched at all,
//hence jQuery will not bind to anything
//and nothing will ever fire!
//note the #delete for Id! .delete is for a class!!!!!!
$('.item #delete').click(function () {
var elem = $(this).closest('.item');
$.confirm({
'title': 'Delete Confirmation',
'message': 'Delete?',
'buttons': {
'Yes': {
'class': 'blue',
'action': function () {
//elem.slideUp();
$.ajax({
url: 'locationsaction.php',
type: 'post',
data: {
lid: "VALUE",
type: 'Delete' //you need to add the type here!
},
success: function () {
img.parent().fadeOut('slow');
}
});
}
},
'No': {
'class': 'gray',
'action': function () {} // Nothing to do in this case. You can as well omit the action property.
}
}
});
Also, you can redudantly add a false return to your form's onsubmit event.
Actually I don't find any button of id btn-delete on your form.If your using delete button present in form then change this
<input type="submit" value="Delete Record" />
to
<input type="button" id="btn-delete" value="Delete Record" />
Or your using any other input then make sure that it type is not submit for example
<input type="submit" value="Your button" />
should be
<input type="button" value="Your button" />
u can use jquery ui dialog for confirmation :
<script type="text/javascript">
$('#btn-delete').click(function (e) {
e.preventDefault();
var elem = $(this).closest('.item'), formSerialize = $(this).parent().serialize(), objParent = $(this).parent();
$('<div></div>').appendTo('body')
.html('<div><h6>Delete?</h6></div>')
.dialog({
modal: true, title: 'Delete Confirmation', zIndex: 10000, autoOpen: true,
width: 'auto', resizable: false,
buttons: {
Yes: function () {
$.ajax({
url: 'deletelocation.php',
type: 'post',
data: formSerialize//,
//success: function (data) {
// objParent.slideUp('slow').remove();
//}
});
//Or
objParent.slideUp('slow').remove();
$(this).dialog("close");
},
No: function () {
$(this).dialog("close");
}
},
close: function (event, ui) {
$(this).remove();
}
});
});
</script>
The problem isn't anything to do with JavaScript.
The fundamental problem seems to be that your form's action is to delete the record (regardless of what you've coded in JavaScript). Change the form's action to "." and onsubmit="return false" (which stops the form from doing anything on its own). Now attaching your $.confirm to the appropriate button should work.
Stepping back from this -- you don't need a form at all (or a submit button). Then you wouldn't have to fight the default behavior of a form.
Try to use e.stopPropagation();
$('#btn-delete').click(function(e) {
e.preventDefault();
e.stopPropagation();

How to write .trigger() code for the template?

I have a table below which contains a textbox and next to the textbox it contains a hyperlink known as "Open Grid". If the user clicks on this link, it opens up a grid and on this grid it displays number buttons from 3 - 26.
<table id="optionAndAnswer" class="optionAndAnswer">
<tr class="option">
<td>1. Option Type:</td>
<td>
<div class="box">
<input type="text" name="gridValues" class="gridTxt maxRow" id="mainGridTxt" readonly="readonly" />
<span href="#" class="showGrid" id="showGridId">[Open Grid]</span>
</div>
<table class="optionTypeTbl">
<tr>
<tr><td><input type="button" value="3" id="btn3" name="btn3Name" class="gridBtns gridBtnsOff">
<input type="button" value="4" id="btn4" name="btn4Name" class="gridBtns gridBtnsOff">
<input type="button" value="5" id="btn5" name="btn5Name" class="gridBtns gridBtnsOff">
<input type="button" value="6" id="btn6" name="btn6Name" class="gridBtns gridBtnsOff">
//...goes all the way to btn26
</tr>
</table>
</td>
</tr>
</table>
Now the code below is able to trigger one of the grid buttons to state that a grid button is clicked. This code is below:
$('#btn'+gridValues).trigger('click');
Now everything above is fine.
THE PROBLEM:
The issue I have is that a user can add a row containing the same template as the option control on top. But within this option and answer control, the user can change an option type if they wish by clicking on one of the grid buttons in this template. So my question is that how do I write the .trigger() to correctly point to a grid button within this template? If you look at the above code, it users the button's id, but if you look at code below which does the template, it doesn't contain an id, it simply just copies the option and control features from above into the template.
Below is the template:
function insertQuestion(form) {
var context = $('#optionAndAnswer');
var $tbody = $('#qandatbl > tbody');
var $tr = $("<tr class='optionAndAnswer' align='center'>");
var $options = $("<div class='option'>Option Type:<br/></div>");
var $questionType = '';
$('.gridTxt', context).each( function() {
var $this = $(this);
var $optionsText = $("<input type='text' class='gridTxtRow maxRow' readonly='readonly' />")
.attr('name',$this.attr('name')+"[]")
.attr('value',$this.val())
.appendTo( $options )
.after("<span href='#' class='showGrid'>[Open Grid]</span>");
$questionType = $this.val();
});
$td.append($options);
$tbody.append($tr);
}
UPDATE:
I have created a URL for this application here. Please follow the steps to use the application and then you can see what is happening:
Step 1: When you open application, 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 "Option Type" A-D, click on
the "Add" button within this row, the modal window will close and you
see in the grey textbox on right hand side that "Option Type" textbox
equals 4 and it displays the Answer buttons A,B,C and D, this is
because as you remember the option type for that row was "A-D".
Now this works fine but it only works for the top option and answer control, follow the steps below:
Step 4: Click on the "Add Question" button, it adds a row underneath
containing the details from the option and answer control on top.
Step 5: Within the row you have just added, you see a green plus
button on left hand side, click on this button and perform the same
search "AAA" in search box.
Step 6: This time select the last row by clicking on its "Add"
button, the "Option Type" for this row is "A-G" so it should display
"Answer" buttons A,B,C,D,E,F and G, but it doesn't do this, it still
states "A,B,C,D".
So how do I change the answer buttons display in the option and answer control within one of the appended rows?
The addwindow() function you see in the view source in the application is the function which occurs after the "Add" button is clicked on. The "Add" button is in an included PHP script and the code for this button is below and with it are all the columns you see after you have performed a search in the modal window:
echo "<table border='1' id='resulttbl'>
<tr>
<th class='questionth'>Question</th>
<th class='optiontypeth'>Option Type</th>
<th class='noofanswersth'>Number of <br/> Answers</th>
<th class='answerth'>Answer</th>
<th class='noofrepliesth'>Number of <br/> Replies</th>
<th class='noofmarksth'>Number of <br/> Marks</th>
</tr>";
foreach ($searchResults as $key=>$question) {
echo '<tr class="questiontd"><td>'.htmlspecialchars($question).'</td>';
echo '<td class="optiontypetd">'.htmlspecialchars($searchOption[$key]).'</td>';
echo '<td class="noofanswerstd">'.htmlspecialchars($searchNoofAnswers[$key]).'</td>';
echo '<td class="answertd">'.htmlspecialchars($searchAnswer[$key]).'</td>';
echo '<td class="noofrepliestd">'.htmlspecialchars($searchReply[$key]).'</td>';
echo '<td class="noofmarkstd">'.htmlspecialchars($searchMarks[$key]).'</td>';
echo "<td class='addtd'><button type='button' class='add' onclick=\"parent.addwindow('$question','$searchMarks[$key]','$searchNoofAnswers[$key]','$searchOption[$key]','$searchReply[$key]','$searchAnswer[$key]');\">Add</button></td></tr>";
}
echo "</table>";
I'm afraid I must be the bearer of bad news. The problem you are having stems from the overall design. Your HTML and javascript really need a bottom-up overhaul with the aim of getting all javascript into a single $(function(){...}) structure, and thus into the same scope. To achieve this you will need to :
Attach all event handlers in javascript in favour of the HTML attribute approach (currently hybrid).
Purge the iFrame in favour of fetching previous questions via AJAX.
In the process you will also purge some duplicate click handling (plus button img and its <a>...</a> wrapper).
Then, you can start to find a solution to your problem :
Delegate all event handling associated with the original "Option and answer" block to a container that is common to it and all future "Option and answer" blocks. The common container may be document but preferably something more specific. This appears to be partly achieved already.
Ensure that all internal referencing within the original "Option and answer" block works with classes rather than ids. .closest() and .find() will be useful here.
On clicking the "+" button, store a reference to the "Option and answer" block (eg. a jQuery object representing its container, discovered relatively). Easiest approach is to store this reference in a variable in the $(function(){...}) scope. (Now you are benefiting from making all those structural changes). The "Add" buttons' click handler will use this reference to affect the correct "Option and answer" block.
On "Add Question", use jQuery's .clone(true, true) to make a copy of the original block (then insert the clone into the DOM). If the other fixes have been applied, then all functionality (click handlers) will attach to the clone automatically.
I work quite quickly but it would still allow 1-2 days for this.
Here's how I would organise the javascript.
$(function() {
// **********
// Data area
// **********
var $$ = { // reusable static jQuery objects
'optionTypeTbl': $('#optionTypeTbl'),
'o_and_a_proto': $("#proto"),
'o_and_a_extras': $("#extras"),
'modal': $("#modal")
},
$o_and_a_section = null;
// ******************
// Utility functions
// ******************
function trim(str) {
return str.replace(/(^\s*)|(\s*$)/gi, "") // removes leading and trailing spaces
.replace(/[ ]{2,}/gi," ") // replaces multiple spaces with one space
.replace(/\n +/,"\n"); // Removes spaces after newlines
}
// ****************
// Initial actions
// ****************
$$.modal.hide();
$("input.gridBtns").removeClass("gridBtnsOn");
$("input.answerBtns").removeClass("answerBtnsOn");
$$.optionTypeTbl.hide();
// code above makes sure all buttons start in the OFF state (so all button are white).
// **********************************************
// Handlers for elements inside the main window
// **********************************************
$(document).on('click', function() {
$$.optionTypeTbl.fadeOut('slow');
});
$("input.gridBtns", $$.optionTypeTbl).on('click', function() {
var $this = $(this);
var $container = $this.closest('.optionAndAnswer');
$container.find(".gridBtns").removeClass("gridBtnsOn");
$this.addClass("gridBtnsOn");
$container.find(".gridTxt").val($this.val());
//$container.siblings('span[name=gridValues[]]').val($this.val()); // ???
$container.find('.answerBtns').each(function(index) {
if (index < Number($this.val())) {
$(this).show();
} else {
$(this).hide();
}
});
});
$$.o_and_a_proto.find(".showGrid").on('click', function(e) {
var $this = $(this);
var $container = $this.closest(".optionAndAnswer");
$("input.gridBtns").removeClass("gridBtnsOn");
var value = $container.find(".gridTxt").val();
//$("#btn" + value.replace(/\s/g, '')).addClass("gridBtnsOn"); //???
$$.optionTypeTbl.appendTo($this.closest("div.box")).show().css({
left: $this.position().left,
top: $this.position().top + 20
});
e.stopPropagation();
});
$$.o_and_a_proto.find(".plusimage").on('click', function() {
$o_and_a_section = $(this).closest(".optionAndAnswer");
$$.modal.modal();
});
$$.o_and_a_proto.find(".answerBtns").on('click', function() {
//btnclick(this); // ???
});
$("#addQuestionBtn").on('click', function insertQuestion() {
$$.optionTypeTbl.hide().appendTo(document);//ensure this itinerant table is not cloned
$$.o_and_a_extras.append($$.o_and_a_proto.clone(true,true).attr('id','')).find("span#plussignmsg").remove();
});
// **********************************************
// Handlers for elements inside the modal window
// **********************************************
$$.modal.find("#close").on('click', function() {
$.modal.close();
return false;
});
$$.modal.find("form").on('submit', function() {
var form = $(this).get(0);
$.ajax({
url: 'previousquestions.php',
data: {
'searchQuestion': 1,
'questioncontent': trim(form.questioncontent.value)
},
type: "get",
success: function(html) {
$("#searchResults").html(html);
},
error: function() {
alert("Something went wrong");
}
});
return false;
});
$$.modal.find("#searchResults").on('click', 'button.add', function() {
var $container = $(this).closest("tr");
var g = $container.find("optiontypetd").data('g');
var btn = $container.find("answertd").text();
$o_and_a_section.find("input.gridTxt").val(g);
if($o_and_a_section.closest("#detailsBlock").length) { //if is original Options and Answers section
//do something ???
//$('#btn'+g).trigger('click'); //???
}
$.modal.close();
});
});
This works to an extent, but please note that it requires associated changes to the HTML and CSS.

Categories

Resources