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

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.

Related

tricky situation with ajax, php, mysql, and javascript

First time using ajax. Have successfully progressed through a number of teething problems, so far with happy results. However now is a more confusing one specific to one particular input field nested within a table - there is a good reason for that.
First the html:
<table id="speakersName" style="width: 100%; height: auto;">
<tbody><tr class="activity_row">
<td class="right" style="width: 190px;">Name of Speaker:</td>
<td><input type="text" id="input_3_1" name="input_3_1" id="input_3_1" placeholder="Name of Speaker" value="<?=$input_3_1?>" required></td>
<td><input type="button" name="button2" id="button2" value=" +1 " class="button" style="width: auto !important; margin: 5px;"></td>
</tr>
<tr>
<td class="center" colspan="3"><input type="hidden" name="MAX_FILE_SIZE" value="5632000">
<label for="file">Filename:</label> <input type="file" name="file" id="file">
<input class="button" style="width: 70px; margin-top: 12px;" type="submit" name="submit" value="Upload"></td>
</tr></tbody>
</table>
We can fairly much ignore the section containing the file upload. I just wanted to be clear about the entire table structure.
The .js file that is included in the head contains this relevant code:
function doSend_3_1() {
$.post('./post.4.ConSupAp.php?appID=' + (appID) + '&ident=input_3_1', $('#input_3_1').serialize());
}
$("document").ready(function() {
$("#input_3_1").blur(doSend_3_1);
})
Which ajax's the data entered into the text input field over to this bit of php:
// include the funcky stuff
include './conf/Funcs.php';
include './conf/DBconfig.php';
// GET the constants
$appID = $_GET['appID'];
$ident = $_GET['ident'];
if(($ident) == "input_3_1") {
$userInput = $_POST['input_3_1'];
if(($userInput == "") || ($userInput == " ") || ($userInput == NULL)) { $userInput = NULL; }
try {
$stmt = $conn->prepare("UPDATE $database.app_ConSupAp SET `nameOfSpeakers` = :userinput, `lastModified` = :time WHERE `appID` = :appid");
$stmt->bindParam(':userinput', $userInput, PDO::PARAM_STR, 128);
$stmt->bindParam(':time', time(), PDO::PARAM_INT, 11);
$stmt->bindParam(':appid', $appID, PDO::PARAM_INT, 11);
$stmt->execute();
} catch(PDOException $e) { catchMySQLerror($e->getMessage()); }
}
Which happily drops in the text that the user typed into the initial text input field, soon as they click out of it. This technique is being used across the form successfully.
True I don't yet have a success or error message coming back to the user facing page, but I'll get onto that after I've sorted this query out. One thing at a time, right? :)
Ok so now I'll show what makes the particular table input (the one above the file upload ) a little more complicated. In the head of the html facing page, I have also got the following code, within a tag:
$(window).load(function() {
// trigger event when button is clicked
$("#button2").click(function() {
// add new row to table using addTableRow function
addTableRow($(this),$("#speakersName"));
// prevent button redirecting to new page
return false;
});
// function to add a new row to a table by cloning the last row and incrementing the name and id values by 1 to make them unique
function addTableRow(btn,table) {
// clone the last row in the table
var $tr = btn.closest($("tr")).clone(true);
var num; // Current unique field number
// Clear the input fields (that are not the button)
$tr.find(":not(:button)").val("");
// get the name attribute for the input field
$tr.find("input").attr("name", function() {
// break the field name and its number into two parts
var parts = this.id.match(/(\D+)(\d+)$/);
num = parts[2]; //Get the number for later
// create a unique name for the new field by incrementing the number for the previous field by 1
return parts[1] + ++parts[2];
// repeat for id attributes
}).attr("id", function() {
var parts = this.id.match(/(\D+)(\d+)$/);
return parts[1] + ++parts[2];
});
btn.remove();
num++;
// append the new row to the table
$(table).find(".activity_row:last").after($tr);
};
});
And this function works wonderfully on it's own, it pops up new table rows for other input, in a nice unlimited manner. I've used a variation on this once before (for which it was originally written for) but that was not utilising ajax. This version works as expected for the initial input value, but I believe I need some sort of JS foreach function to arrange each of the additional new input text fields into one value, separated by a delimiter such as ^ so that I can break them up in the php and count them there with an explode and foreach.
jQuery is being used.
This is where I'm lost as I do not know how to achieve this. Help warmly received. :)
I carefully study your job at http://jsfiddle.net/k3dj214k/2/
Now, I will try explain all the steps to fix errors:
The form page html:
<form id="ConSupAp_section_3" name="ConSupAp" action="./post.4.ConSupAp.php" method="post" enctype="multipart/form-data"><!-- edited by kazumov#gmail.com -->
<input type="hidden" name="token" value="3e57334833283e22579f77e3a1ade083edf637bd3f4ab8009bbf1f4d7f517fde">
<input type="hidden" name="uID" value="1">
<input type="hidden" name="uaID" value="1">
<input type="hidden" name="appID" value="1">
<input type="hidden" name="ident" value="input_3_1"><!-- edited by kazumov#gmail.com -->
<h2 style="margin: 0 auto 20px;">Conference Support Application - Section 3</h2>
<table id="speakersName" style="width: 100%; height: auto;">
<tbody>
<tr>
<td colspan="3" style="padding: 30px;"><span class="h3">3.1</span>Please list names of guest speaker(s). Use the <strong>+1</strong> button to add addtional speakers.</td>
</tr>
<tr class="activity_row">
<td class="right" style="width: 190px;vertical-align:top">Name of Speaker:</td>
<td id="speakers_list"><!-- edited by kazumov#gmail.com -->
<!--<input type="text" name="s" placeholder="Name of Speaker" value="" required>--><!-- edited by kazumov#gmail.com -->
</td>
<td>
<input type="button" id="btnAddSpeaker" value=" +1 " class="button" style="width: auto !important; margin: 5px; vertical-align:bottom"><!-- edited by kazumov#gmail.com -->
</td>
</tr>
</tbody>
</table>
</form>
I added one hidden input and delete text input. The form tag id should be renamed to ConSupAp_section_3.
The app_ConSupAp.js editions:
Kill doSend_3_1() function
// edited by kazumov#gmail.com
//function doSend_3_1() {
// $.post('./post.4.ConSupAp.php?appID=' + (appID) + '&ident=input_3_1', $('#input_3_1').serialize(), function(data) {
// $("#errorText_3_1").html(data.errorText_3_1);
// $("#resultImg_3_1").html(data.resultImg_3_1);
// }, 'json');
//}
Kill whole module for names manipulation:
// edited by kazumov#gmail.com
// // trigger event when button is clicked
// $("#button2").click(function() {
// // add new row to table using addTableRow function
// addTableRow($(this), $("#speakersName"));
// // prevent button redirecting to new page
// return false;
// });
//
// // function to add a new row to a table by cloning the last row and incrementing the name and id values by 1 to make them unique
// function addTableRow(btn, table) {
// // clone the last row in the table
// var $tr = btn.closest($("tr")).clone(true);
// var num; // Current unique field number
// // Clear the input fields (that are not the button)
// $tr.find(":not(:button)").val("");
// // get the name attribute for the input field
// $tr.find("input").attr("name", function() {
// // break the field name and its number into two parts
// var parts = this.id.match(/(\D+)(\d+)$/);
// num = parts[2]; //Get the number for later
// // create a unique name for the new field by incrementing the number for the previous field by 1
// return parts[1] + ++parts[2];
// // repeat for id attributes
// }).attr("id", function() {
// var parts = this.id.match(/(\D+)(\d+)$/);
// return parts[1] + ++parts[2];
// });
// btn.remove();
// num++;
// // append the new row to the table
// $(table).find(".activity_row:last").after($tr);
// };
append the script page with:
// ---------------------------------------------------
// code addition for phase (3) "Speakers" of "Guests"
// edited by kazumov#gmail.com
// ---------------------------------------------------
$(document).ready(function() {
function addSpeakerNameField() {
var $txtInput = $("<input type=\"text\" name=\"speakers[]\" placeholder=\"Name of Speaker\" value=\"\" required />");// extended notation to create input element, 'id' is not nesessary
$("#speakers_list").append($txtInput);
$txtInput.blur(function(){// change value event
$.post(
"post.4.ConSupAp.php", // your address of page is different, i made temporary php page to debug
$("#ConSupAp_section_3").serialize(),// get all form values
function(data) {
// actually, your html have no tags with id "errorText_3_1" and "resultImg_3_1"
$("#errorText_3_1").html(data.errorText_3_1);// not working
$("#resultImg_3_1").html(data.resultImg_3_1);// not working
},
'json');
});// end of blur()
}
addSpeakerNameField();// the first field
$("#btnAddSpeaker").click(function() { // add one more field
addSpeakerNameField();
});
});
// end of edition by kazumov#gmail.com
As you can see, the important editions are:
a) you should generate all the input text fields from code, because it will create the whole sending routine for all the fields in one place;
b) you should naming the text fields in html like name="speaker[]", because it will create array after serialization;
c) you should adding hidden inputs inside the form, if you want to send static values;
d) i recommend you delete all over-navigation:
and rename the tabs:
Finally, in post.4.ConSupAp.php you will reach the names:
$speakers = $_POST["speakers"];// returns array
And you should to add the header to the post.4.ConSupAp.php
header("Content-type: application/json");
if you expecting the data.errorText_3_1 and data.resultImg_3_1 output to the form.
This looks like a situation where you have a jquery event you would like to bind to a number of elements, but not all of those elements have been created when the event - blur() - is bound.
You can bind events to higher DOM element and use the following syntax to bind events to new elements as they are created:
$("body").on("blur", "input.some_class_name", do_send);
When do_send() is called, "this" will be defined as the element where the event was generated, so you can identify which element needs to be posted:
function do_send(e) {
// "this" is the dom element
var the_id = $(this).attr('id');
var value = $(this).val();
// post away!
}

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

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();

JQuery Ajax call stop refresing the page

I have the following html code:
<div>
<form id="ChartsForm">
<div id="optionsheader">
<p>Choose your page:</p>
<div id="dateoptions">
<p>Until date: <input type="date" name="until_date" value="Until date"></p>
<p>Since date: <input type="date" name="since_date" value="Since date"></p>
</div>
</div>
<select name="accmenu" id="accmenu" style="width:300px; float:left; clear:both;">
<?php
$user_accounts = $facebook->api('/me/accounts','GET');
foreach($user_accounts['data'] as $account) {
?>
<option data-description="<?php echo $account['category'] ?>" data-image="https://graph.facebook.com/<?php echo $account['id']; ?>/picture" value="<?php echo $account['id'] ?>"><?php echo $account['name'] ?></options>
<?php
}
?>
</select>
<div class="insightsoptions">
<p>Choose your insights:</p>
<input id="newLikes" class="insightsbuttons" type="submit" name="submit" value="Daily new likes">
<input id="unlikes" class="insightsbuttons" type="submit" name="submit" value="Daily unlikes">
</div>
<div class="insightsgraphs">
<div id="dailyNewLikes"></div>
<div id="dailyUnlikes"></div>
</div>
</form>
</div>
which has a form with the id=ChartForm that contain two date inputs until_date and since_date, one select accmenu and two submit inputs with the values Daily new likes and Daily unlikes. I use the following Jquery function:
$(function () {
$('#accmenu').change(function() {
$(".insightsgraphs div").hide();
$(".insightsoptions input").attr("class","insightsbuttons");
});
$("#newLikes").one('click', function () {
$.ajax({type:'GET', url: 'newLikes.php', data:$('#ChartsForm').serialize(), success:
function(response) {
var json = response.replace(/"/g,'');
json = "[" + json + "]";
json = json.replace(/'/g,'"');
var myData = JSON.parse(json);
var myChart = new JSChart('dailyNewLikes', 'line');
myChart.setDataArray(myData);
myChart.setSize(960, 320);
myChart.setAxisNameX('');
myChart.setAxisValuesColorX('#FFFFFF');
myChart.setAxisNameY('');
myChart.setTitle('Daily New Likes');
myChart.draw();
}});
return false;
});
$("#newLikes").on('click', function(){
$(this).toggleClass('green');
$('#dailyNewLikes').toggle();
});
$("#unlikes").one('click', function () {
$.ajax({type:'GET', url: 'unlikes.php', data:$('#ChartsForm').serialize(), success:
function(response) {
alert(response);
$("#dailyUnlikes").html(response);
}});
return false;
});
$("#unlikes").on('click', function(){
$(this).toggleClass('green');
$('#dailyUnlikes').toggle();
});
});
for the application flow in the following manner: every time I click on one of the input submit buttons the script will make only one Ajax GET request to a specific php file that send me back a response with which I create a Chart in a hidden div with the id=dailyNewLikes or id=dailyUnlikes by case (for testing purposes I work for the moment only on the first button). The button it will change his background color into green and the div it will be shown. I use $("#newLikes").on('click', function(){ for change back and forth the background color and the display time of the div. (from green and display:block to red and display:none, you get the point I hope :D). Also I use $('#accmenu').change(function() { to change all buttons to red and hide the respective div in case an option from the select is changed. My problem is that after I refresh the page (Ctrl+R) choose since and until date, click on the first button (it change to green and the div is shown, also the toggle is working fine) and then click on the second button which works fine on the first click (is becoming green and div is shown) but on the second click I have an issue: the script is making another Ajax GET request (a wrong URL one) and the page is refreshed. Ex. of a good reguest URL:
http://localhost/smd/unlikes.php?until_date=2013-05-01&since_date=2013-04-01&accmenu=497232410336701
and an ex. of a wrong request URL:
http://localhost/smd/?until_date=2013-05-01&since_date=2013-04-01&accmenu=497232410336701&submit=Daily+unlikes#_=_
Like it can be seen (it doesn't need in the first to make this extra request) the php file is not present and also a new submit parameters is added. This also happen if I change from the select with another option. What am I do wrong? I really need to know, not just to have my code "fixed". It bugging me for a little while. Any feedback is more than welcomed. P.S. Also, how can I start the .one function only if both date inputs has been choosen? Something like how could help me?
var until = $('#dateoptions input[name="until_date"]').val();
var since = $('#dateoptions input[name="since_date"]').val();
if (until == "" || since == "") {
alert('Until date or Since date missing!');
return;
}
it will work that way? Sorry for the long question...
i think you should make your question a little shorter and just point what you need and what errors are you getting ..anyways...going through your code i see you have two click event for same button at the end for $("#unlikes").one and $("#unlikes").on(..and no return false in other function.
try adding return false
$("#newLikes").on('click', function(){
$(this).toggleClass('green');
$('#dailyNewLikes').toggle();
return false;
});
$("#unlikes").on('click', function(){
$(this).toggleClass('green');
$('#dailyUnlikes').toggle();
return false;
});
my guess is that , since you have two click event..when it gets clicked ..these event will fire and since you are missing return false in second click function...the form gets submitted hence refreshing the form.
however its better if put your codes in single click function than creating two seperate click event.

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();

creating an inline update field using jquery

I've gotten stuck(again)
I have a table and one of the columns is a value that I want to be able to click, turn into an input field, then click again to change it back to just text.
I've gotten the first step done. It turns into an input field with a link to click and it uses the value that was previously in the td.
However, in writing the function to update the value and remove the input, I can't get it to fire at all. I've tried copying out the input field and hard coding that first step into the page and when I do that it does actually fire the click function. (I haven't finished writing this step as I wanted to get the function to fire first. Below is my code. Any help is overwhelmingly appreciated!
HTML:
<table>
<tr id="1"><td class="qty" set="0" >2</td></tr>
<tr id="2"><td class="qty" set="0" >2</td></tr>
<tr id="3"><td class="qty" set="0" >2</td></tr>
</table>
JQUERY:
$(".qty").click(function(){
var value = $(this).text();
var set =$(this).attr('set');
if (set==0){
$(this).html('<input type="text" name="quantity" value="'+value+'">update </span>');
$(this).attr('set', '1');
}
});
$(".update_qty").click(function(){
alert("using this to check if it's firing");
});
you need to use the live() function, otherwise the event won't be added to newly created elements.
$(".update_qty").live('click',function() {
alert("check if firing");
});
demo
http://jsfiddle.net/JEBaN/1/
some value
<br><br>
<a href='javascript:' id='toEdit'>To Edit Mode</a>
<a href='javascript:' id='toView'>To View Mode</a>​
jQuery(function(){
jQuery('#toEdit').click(_toEditMode);
jQuery('#toView').click(_toViewMode);
});
function _toEditMode()
{
var _elm=jQuery('.converter');
var _val= _elm.html();
_elm.html('<input type="text" value="'+_val+'" />');
}
function _toViewMode()
{
var _elm=jQuery('.converter');
var _val= _elm.find('input').val();
_elm.html(_val);
}
​
$(".update_qty").click(function(){
$("qty").html("<p>whatever text you want</p>");
});

Categories

Resources