I am dynamically generating two paragraphs and two input fields inside a div. There may be numerous divs generated, depending upon the number of records pulled from the database. Each para and input field is assigned a unique id.
When the user clicks on a field, say firstText_id, jQuery hides the field and shows an input field firstText_input_id in its place. The user updates the input field, and on clicking away, an ajax script is called to update the database and return a success message.
My problem is that, when the user clicks on one field in any record, and updates it, then clicks away, the ajax calls for both fields are made.
PHP
echo "<div class=\"single seven columns boxTable2 \" id=\"{$vid}\">
<div class=\"seven columns alpha omega\" >
<div class=\"four columns alpha omega\" >
<p class=\"single two columns alpha omega firstHead\">First name: </p>
<p class=\"firstText single two columns alpha omega\" id=\"firstText_{$vid}\"
data-vid=\"{$vid}\">{$first}</p>
<input type=\"text\" id=\"firstText_input_{$vid}\"
class=\"firstText_input single two columns\"
data-vid=\"{$vid}\" value=\"{$first}\"/>
</div>
<div class=\"four columns alpha omega\" >
<p class=\"single two columns alpha omega lastHead\" >Last name: </p>
<p class=\"lastText single two columns alpha omega\" id=\"lastText_{$vid}\"
data-vid=\"{$vid}\">{$last}</p>
<input type=\"text\" id=\"lastText_input_{$vid}\"
class=\"lastText_input single two columns\"
data-vid=\"{$vid}\" value=\"{$last}\"/>
</div>
</div>
</div>
jquery
jQuery.noConflict();
jQuery(document).ready(function($){
var vidID = '';
$(document).on('click', '.firstText', function ()
{
vidID=$(this).data('vid');
$('#firstText_'+vidID).hide();
$('#firstText_input_'+vidID).show();
}).change(function()
{
var newFirstText=$('#firstText_input_'+vidID).val();
var firstTextDataString = 'vid='+ vidID +'&first='+newFirstText;
if(newFirstText.length>0)
{
$.ajax({
type: "POST",
url: "/go/to/php.php",
data: firstTextDataString,
cache: false,
success: function(html)
{
$('#firstText_'+vidID).html(newFirstText);
}
});
} else
{
alert('Enter something.');
}
});
// Edit input box click action
$('.firstText_input').mouseup(function(e)
{
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
// return false; //(does the same as the above 3 functions)
});
// Click away action
$(document).mouseup(function()
{
$('.firstText_input').hide();
$('.firstText').show();
});
$(document).on('click', '.lastText', function ()
{
vidID=$(this).data('vid');
$('#lastText_'+vidID).hide();
$('#lastText_input_'+vidID).show();
}).change(function()
{
var newLastText=$('#lastText_input_'+vidID).val();
var lastTextDataString = 'vid='+ vidID +'&last='+newLastText;
if(newLastText.length>0)
{
$.ajax({
type: "POST",
url: "/go/to/php.php",
data: lastTextDataString,
cache: false,
success: function(html)
{
$('#lastText_'+vidID).html(newLastText);
}
});
} else
{
alert('Enter something.');
}
});
// Edit input box click action
$(".lastText_input").mouseup(function()
{
return false;
});
// Click away action
$(document).mouseup(function()
{
$(".lastText_input").hide();
$(".lastText").show();
});
});
As the unique IDs are generated dynamically from the database records, I can’t find a way of associating the user’s click to the field being updated without the other field in the record being updated. I’m a relative beginner with jQuery/javascript. How can I isolate the user’s action to the field being clicked? I have tried click selectors like ‘[id^=”firstText_input_”]’. Probably a simple error, but I have been round it too many times to see the error.
The event that causes the ajax to happen is actually bound to the document, therefore, anytime ANY input changes, the document receives the event and performs the ajax request.
See below:
$(document).on('click', '.someclass', function () {...}).change(function () {...});
.change is targeting $(document), not $('.someclass'), you'll have to use the same delegation syntax as before to instead delegate it to the target element.
$(document).on('click', '.someclass', function () {...}).on('change', '.someclass', function () {...});
both firstText and lastText are affected by this issue, which is why both trigger any time you change either input.
Additionally... your event binding is very inconsistent. In some cases you're using delegation, and in others you are not. Since you're replacing the entire content of the div, you should be using event delegation for all of the events within that div.
Related
I have listed my table(leaveform) records(50) using datatable API. In my table I have a column to approve leave. This column consist of two radio buttons(Approve and Reject). Each record have its own unique id. Now I want to update the values into database using those unique id.
This is my Table
You can create one function and that function is called by clicking on 'Approve' or 'Reject'. Let me give you example.
For e.g. : you have two radio button as below.
Approve and Reject
Now, You have to create one function that will be called by clicking on radio button. as explained below.
<input type="radio" name="rndLeave" value="approve" onclick="changeLeaveStatus(leaveid, 'approve')" /> Approve
<input type="radio" name="rndLeave" value="reject" onclick="changeLeaveStatus(leaveid, 'reject')" /> Reject
// first argument is leave id
// second argument is leave status.
function changeLeaveStatus(leaveid, leaveStatus)
{
$.ajax({
url: 'leave_status.php',
data: 'id='+leaveid+'&status='+leaveStatus,
type: 'POST',
success: function() {
},
error: function(){
}
});
}
This way you can update leave status from jquery datatable.
I see your tag has jquery so I guess you may want jquery code for solve this problem. here it is.
$( "#button_update" ).click( function() { //on click button update
var approve = new Array();
for (i=1;i<=count;i++) {
if ($('#id' + i).attr('checked') == 'checked'){
approve[i-1] = $('#id' + i).attr('id');
}
}
$.post(url,
{ approve: approve },
function(data) {
});
});
you should use jquery onclick on table with handler "tr" -> send ajax data to update.
$( "#dataTable tbody" ).on( "change", "input[type=radio]", function() {
console.log( $( this ).text() );
$.get( "path_to_php_page/update.php?id="+$( this ).attr("id")+"&state="+$(this).children("input[type=radio]:checked").val(), function( data ) {
console.log( data );
});
});
in update.php
you should get the id of the row with $_GET['id'] and the state with $_GET['state']
(simplified) Scenario: a remote MySql DB and an HTML page with 2 buttons: SHOW and SELECT. The SHOW loads a single record and displays the fields in a form.
Everything is ok on this side.
The SELECT was made with a new approach for me:
I pass a parameter to a PHP function to query the DB and create an html file with the resuls.
This file is a series of <UL><LI><a id="1"...data..</LI></UL> to be inserted within a DIV.
One of the <LI> contains a link that, when clicked, calls the SHOW function. The record identification is made by mean of the ID associated to the anchor.
This procedure works fine; I get the new HTML segment (that I can check on the remote web server).
It is inserted (???) inside my DIV and the content is correctly displayed on screen, but... it does not exist.
Clicking on the links does not activate the SHOW procedure (actually, an Alert with the calling ID is never shown).
Looking to the html page source from Mozilla it still shows the previous content, without the new added (or replaced) code.
This is the reason for this post's title: I see something that really is not there.
Possibly, I should have AJAX to 'refresh' its visibility of the DOM, but and do not understand how.
This is the piece of JQuery script that I use to get the new content:
$("#select").click(function() {
$.ajax({
url: "new_record_list.php",
cache: false,
success:
function(recNumber)
{
$("#selected").val(recNumber); //ok
$("#recordList").load("list.txt"); //'list.txt is created by new_record_list.php
alert($("#recordList").html()); //this is OK
}
});
});
Everything is ok, but where is the meat?
Most likely the listener you created did not attach to the new dom nodes.
You can fix this by attaching a listener to a parent element that exists at page creation or even the document like so:
$(document).on('click', '.show', function() {
//click event
});
Replace ".show" with the jquery selector for the links
Since I'm unable to comment on your new post due to rep:
Remove the click event handler inside the loadRecord function.
The click event was already bound at the top of your script. What happens is that you click, activate the load record function which binds a new click handler, triggering the action on all the clicks following it.
The load record should look like this instead:
function loadRecord(){
ind = $(this).attr("id");
$("#thisRecord").val(ind); //shows the clicked record
$.get("show_record.php",{id:ind}, function(gotString)
{
ptr=0; //used to fetch fields
pos=0;
lun = gotString.length;
if (lun==0) {
alert ("Empty string!");
return false;
};
// fetch received keys and values then fills the fields
while (ptr < lun) {
..... //not interesting here
}; //while
});
return false; //required!
};
Also, you should replace
$(document).on('click', '.compLink', function() {
loadRecord();
});
with
$(document).on('click', '.compLink', loadRecord);
And loadRecord will be passed the mouse event as an argument. $(this) will also refer to the link you clicked inside the loadrecord function.
Otherwise you need to pass the element clicked into that function.
One issue I can see straight away is the AJAX call, it should be along the lines of:
$( "#select" ).on( "click", function ()
{
$.ajax( {
url: "new_record_list.php?record=MY_RECORD_VALUE",
type: "GET",
success: function ( response )
{
$( "#selected" ).val( response );
$( "#recordList" ).html( function ()
{
$.ajax( {
url: "list.txt",
typ: "GET",
success: function ( response2 )
{
$( "#recordList" ).html( response2 );
}
} );
} );
alert( $( "#recordList" ).val() );
},
beforeSend: function()
{
$( "#recordlist" ).html( "Loading..." );
$( "#selected" ).val( "Loading..." );
}
} );
} );
This will give a better result from the $.ajax call that you have made.
The .load() method can be quite unreliable at times, hence why it is (IMO) better to make an ajax within an ajax, because that's what your doing with less control effectively.
Where you have done the function(recNumber) is kinda wrong I'm afraid, whats brought back from the AJAX call is the response, everything that would be shown should you be using it as an actual page, e.g. if you had:
<table>
<tr>
<td>Row 1</td>
</tr>
<tr>
<td>Row 2</td>
</tr>
</table>
<input id="id_valued" value="2" />
Then this whole thing would be returned, not just the id_valued input field.
I followed the hints from Erin plus some other suggestion found on this forum and now the program ALMOST works.
Actually it does, but when a new set of records is loaded, to update the display (that is to call the loadRecord function) it is necessary to click twice on a link, the very first time only. All next clicks reacts immediately.
I try to post the entire script, for you experts to see what I hardly did:
<script type="text/javascript">
$(document).ready(function()
{
$(document).foundation();
var $scrollbar = $("#scrollbar1"); //other stuff
$scrollbar.tinyscrollbar();
//Erin suggestion + my understanding
$(document).on('click', '.compLink', function() {
loadRecord();
});
/* =========== ADD Rows ============================== */
/* action called by hitting the "selectRow" button.
/* query the DB and get a list of rows (5 fields each)
/* that are then inserted into the '#recordList' DIV.
/* Each rows has format:
/* <UL><LI><A id="xxx" class="compLink" ...>item xxx</A></LI><LI>....</LI></UL>
*/
$("#selectRow").on( "click",function()
{
$.ajax(
{
url: "new_record_list.php",
type: "GET",
success: function(recNumber) //if ok, we get the number of records
{
$("#selectedRecords").val(recNumber); //show how many records we got
$("#recordList").load("newRecords.txt"); //loads the remote text file into the DIV
}
});
});
/* ====================================================== */
/* =========== LOAD Record ============================== */
/* loads and displays an entire record from DB,
/* based on the ID of clicked link with class="compLink"
/* in '#recordList' DIV.
/* Example: <a id="1" class="compLink" ...>
*/
function loadRecord(){
$(".compLink").click(function(event)
{
ind = $(this).attr("id");
$("#thisRecord").val(ind); //shows the clicked record
$.get("show_record.php",{id:ind}, function(gotString)
{
ptr=0; //used to fetch fields
pos=0;
lun = gotString.length;
if (lun==0) {
alert ("Empty string!");
return false;
};
// fetch received keys and values then fills the fields
while (ptr < lun) {
..... //not interesting here
}; //while
});
return false; //required!
});
};
/* ====================================================== */
return false;
});
</script>
I hope this is clear enough. Thanks
I thought the easiest way would be to explain it with an image of what I have.
Summary -
I have a form to submit posts (pretty much like what you would find in twitter). Within each post there is an <ol> where comments to that post will reside.
Problem -
When I submit the first comment (button submit 2 in the picture), it doesn't call the ajax and just goes to a page where it presents me the php output of the comment. It seems it is not reloading or aplying DOM events to that portion of code. If I go back, the comment is presented (because it refreshs the page) and when adding the 2nd comment, everything goes normal, as expected. The problem is just the first comment.
Flow -
1) insert new post
2) click the textarea, put some text and press submit
3) Jumps to a page where php output for comment is presented
3a) no ajax call is done. It never enters the code
Could you please help me out understand what is going on? Thanks in advance.
In case you need more of the code just tell me.
JS (post_comment.js - associated with submit 2 in picture. I use ajaxForm - jquery form plugin - though I also tried with the standard .ajax call and the result is the same)
$(function () {
var options = {
success: function (html) {
var arrHTML = html.split(',');
var postId = $.trim(arrHTML[0]);
var html_code = arrHTML[1];
$('ol#post_comment_list' + postId).load(html_code);
//$('ol#post_comment_list'+postId 'li:first').slideDown('slow');
$('.footer-post').hide();
$('.comments-feed').delay(2000).slideUp({
duration: 1000,
queue: true
});
$('.small-textarea-main-feed').removeClass('set-large');
resetForm($('.footer-comment'));
},
error: function () {
alert('ERROR: unable to upload files');
},
complete: function () {
},
};
$(".footer-comment").ajaxForm(options);
function ShowRequest(formData, jqForm, options) {
var queryString = $.param(formData);
alert('BeforeSend method: \n\nAbout to submit: \n\n' + queryString);
return true;
}
function resetForm($form) {
$form.find('input:text, input:password, input:file, select, textarea').val('');
$form.find('input:radio, input:checkbox')
.removeAttr('checked').removeAttr('selected');
}
});
Basically, I've got a form that submits a post to my wordpress blog depending what's in the form. When submitted, it hides the form from the page using ajax (as below). This works only when I have 1 form on the page.
What I am trying to do is make multiple forms work the same way on a page... Each one hides only itself when it's submitted.
contact_form is the DIV ID of the singular form that works
I added <div id="form'.$formnumber.'"> to the html page, so now there are multiple forms with IDs of form1, form2, form3, etc. form_no is the number on the end that gets sent to this script.
I don't know ajax/javascript very well - How do I make it work on multiple divs? Here's what I have at the moment (I've simplified as much as possible). Thanks!
$(".button").click(function() {
var form_no = $("input#form_no").val();
}
...further down the page...
$.ajax({
type: "GET",
url: "mypage.php",
data: dataString,
success: function() {
$('#contact_form').html("<div id='message'></div>");
$('#message').html("")
.append("")
.hide()
.fadeIn(1500, function() {
});
}
});
return false;
This does the job:
$(".button").click(function() {
var form_no = $("input#form_no").val();
$('#form' + form_no).hide();
});
I've built star button to use it like "starred items". I have the code running. but i have a problem.
When i click on star it becomes a starred item and and the star image changes.
But when i click again to unstar, it just doesn't work. i need to refresh the page to unstar it.
Also even the first step doesn't work for chrome.
add star codes:
jquery
$(function() {
$(".yildiz").click(function() {
var id = $(this).attr("id");
var dataString = 'id='+id ;
var parent = $(this).parent();
$.ajax({
type: "POST",
url: "yildizekle.php",
data: dataString,
cache: false,
success: function toggle()
{
$('.yildizbutton'+id).animate({
src:"star-icon.png",
class:"yildizsizbutton"+id,
},0);
}
});
return false;
});
});
php:
<img class="yildizsizbutton'.$row['id'].'" border="0" src="star-icon.png" alt="Yildizi kaldir" width="16" height="16" />
remove star
$(function() {
$(".yildizf").click(function() {
var id = $(this).attr("id");
var dataString = 'id='+id ;
var parent = $(this).parent();
$.ajax({
type: "POST",
url: "yildizsil.php",
data: dataString,
cache: false,
success: function toggle()
{
$('.yildizsizbutton'+id).animate({
src:"star-icon-f.png",
class:"yildizbutton"+id,
},0);
}
});
return false;
});
});
php:
<img class="yildizbutton'.$row['id'].'" border="0" src="star-icon-f.png" alt="Yildiz ekle" width="16" height="16" />
To add the star, do something similar to this:
$("#"+id).find("img").attr("src", "star-icon.png");
To remove:
$("#"+id).find("img").attr("src", "sstar-icon-f.png");
You shouldn't use animate in the way you are using it at all. I also used the ID of the container, then found the image inside of it, instead of putting together that class like you were doing. That's just personal preference, though...the main takeaway is to use attr("src") to set the src of an image in jQuery.
EDIT: Here is a full solution that should work.
$(function() {
$(".star").click(function() {
var id = $(this).attr("id");
if($(this).hasClass("starred")) {
$.post("yildizekle.php", {id: id}, function(resp) {
$(this).removeClass("starred").find("img").attr("src", "star-icon-f.png");
});
}
else {
$.post("yildizsil.php", {id: id}, function(resp) {
$(this).addClass("starred").find("img").attr("src", "star-icon.png");
});
}
return false;
});
});
Notice that we are using a class to track whether or not the element is already starred. This means in your PHP you will need to add the starred class to any elements that are already starred when the page loads. Also, I used $.post instead of $.ajax since it is a simpler way of doing the same thing.
There are a few problems in your code, and both of the answers here are relevant and both are correct. Being as green as you are, I'd say you are on the road to learning well.
I'd use a separate class for ALL of the stars, one that doesn't relate to if its starred or unstarred. Maybe something like 'star'. :) You need to refresh the page to un-star it is because you never actually change it on the FRONT-end to be starred. If you use a tool like firebug of WebKit's Web inspector, you'll see that the class of the link is still "yildiz".
I'm not going to give you a complete answer because I'd be robbing you of an awesome learning experience here. Here are some pointers:
Remember which objects your click() events are connected to: $(".yildizf") and $(".yildiz")
When you click on an item, does it actually change class so that jQuery knows it's different? Essentially, you are 'starring' the same item over and over again because you never allow jQuery to see it as something it needs to un-star
If you use a 'star' class in addition to the other class (like <a class="star yildiz" ...>), then you can attach your click event to $('a.star'), and figure out in THERE if you should be starring or unstarring the item.
I hope this all makes sense.
You've defined the click event to both star and un-star the item. In the event you need to look at the current state of the item then decide if you want to star or un-star it. you need to branch inside your click event.