Using jquery UI's dialog() function with ajax call - javascript

I'm trying to show a pop up (using Jquery UI's dialog() function) when user clicks on content inside a table cell. I'm populating the table using data returned from the Ajax call on a REST url. I get the correct data and the table is displayed correctly. The issue is that the click() function for the text inside the table cell doesn't get called.
The culprit seems to be the Ajax call since the the same approach works in case of static data inside the table.
Snippets from the html file:
<head>
$(document).ready(function(){
$("#dlg1").dialog({ autoOpen: false });
$('.linkClass1').click(function() {
$("#dlg1").dialog("open");
});
$.ajax({
url: "http://localhost:8080/abc/rest/def",
type: "GET",
contentType: 'application/json; charset=utf-8',
success: function(resultData) {
var len = resultData.length;
var table = $('<table></table>').addClass('tableClass1');
var hRow = $('<tr></tr>');
var hVar1 = $('<th></th>').addClass('headingClass1').text("col1");
hRow.append(hVar1);
table.append(hRow);
for(i=0; i<len; i++)
{
row = $('<tr></tr>');
var var1 = $('<td></td>').addClass('cellClass1');
var linkVar1 = $('<a>')
.attr('class', 'linkClass1')
.attr('href', '#dummyId')
.text(resultData[i].id);
var1.append(linkVar1);
row.append(var1);
table.append(row);
}
$(table).attr("id","tableId1");
// this table is appended to an html element and is correctly displayed
},
});
});
</head>
<body>
<div id="dlg1" title="Basic dialog">
<p>This is the default dialog which is useful for displaying information. The dialog window can be moved, resized and closed with the 'x' icon.</p>
</div>
</body>
On clicking the text inside table, nothing happens, just the original url is appended with #dummyId. I also tried using an alert() inside the click function and even that is not shown.
Even setting async: false in the Ajax call doesn't help.
If anyone can help, thanks.

Long Answer
Instead of applying a jQuery click handler why don't you use the href or onclick tags to call the desired function as:
function openDialog(){
$("#dlg1").dialog("open");
}
...
for(i=0; i<len; i++) {
row = $('<tr></tr>');
var var1 = $('<td></td>').addClass('cellClass1');
var linkVar1 = $('<a>')
.attr('class', 'linkClass1')
.attr('href', '#dummyId')
.attr("onclick", openDialog)
.text(resultData[i].id);
var1.append(linkVar1);
row.append(var1);
table.append(row);
}
....
You can also afford to remove the click handler you had applied.
Short Answer
Just move the click handler at the end of the success event handler. This will ensure that when the click handler gets applied, all the DOM elements are present on the page.
$(document).ready(function(){
$("#dlg1").dialog({ autoOpen: false });
$.ajax({
url: "http://localhost:8080/abc/rest/def",
type: "GET",
contentType: 'application/json; charset=utf-8',
success: function(resultData) {
var len = resultData.length;
var table = $('<table></table>').addClass('tableClass1');
var hRow = $('<tr></tr>');
var hVar1 = $('<th></th>').addClass('headingClass1').text("col1");
hRow.append(hVar1);
table.append(hRow);
for(i=0; i<len; i++)
{
row = $('<tr></tr>');
var var1 = $('<td></td>').addClass('cellClass1');
var linkVar1 = $('<a>')
.attr('class', 'linkClass1')
.attr('href', '#dummyId')
.text(resultData[i].id);
var1.append(linkVar1);
row.append(var1);
table.append(row);
}
$(table).attr("id","tableId1");
$('.linkClass1').click(function() {
$("#dlg1").dialog("open");
});
},
});
});

At the time of binding to $('.linkClass1').click .linkClass1 doesn't exist yet, either bind to this at the end of your ajax success or use
$('body').on('click', '.linkClass1', function
where it is now.

This code is only ever invoked once:
$('.linkClass1').click(function() {
$("#dlg1").dialog("open");
});
Which means it's only going to find the .linkClass1 elements which exist at the time it's called and only going to bind click handlers to those elements. Remember that handlers are attached to elements, not to selectors.
So what's essentially happening is this code is never assigning a click handler to the elements that are being added after the AJAX call.
You can fix this by delegating the event handling to a common parent element which doesn't change during the life of the DOM. Any parent element will do, document is usually a workable default. Something like this:
$(document).on('click', '.linkClass1', function() {
$("#dlg1").dialog("open");
});
This will assign the click handler to the document instead of the element, and assuming nothing stops the propagation of the event that click will "bubble up" from the clicked element to every parent element, all the way up to document. The second selector in that code is then a filter used to respond only to click events which originated from matching elements.

Related

On click ajax post request not working on click of cell in two tables as expected

Capturing table id and cell text by using below code.
$("td").click(function(e) {
var $row =$(e.target).closest("td"); // Find the row
var $table_label= $row.text();
//alert($table_label);
var $table_id=$(this).closest("table").attr('id');
if($(this).attr('style'))
$(this).removeAttr('style');
else
$(this).css('background', '#309');
tableText($table_label,$table_id); //this is ajax function
});
Ajax funciton:
$test_table1 = $('.test_table1')
$test_table2 = $('.test_table2')
function tableText(table_label,table_id) {
$.ajax({
type: 'POST',
url: url,
contentType: 'application/json',
data: JSON.stringify({'label':'table', 'filter':{'table_id':table_id,'table_label':table_label}}),
success: function(res, status, xhr){
$test_table1.html(res['table1']);
$test_table2.html(res['table2']);
},
});
}
When I click on directly table2 it's working. When I click after clicking on table1 and then in table2 its not working. If I removed ajax function its working fine in both cases.
Any suggestions?
$("td").click(function () { will bind events only to the a elements which are present in DOM.
$(document).on("click", "td", function () { will bind the event on the a elements which are not present at the time of binding event. This is called as event delegation.
Event delegation allows us to attach a single event listener, to a
parent element, that will fire for all descendants matching a
selector, whether those descendants exist now or are added in the
future.
As per your ajax response, tr and td are added to the DOM after the binding of the element.
Instead of using $("td").click(function (), use $(document).on("click", "td", function () {

Change behavior of button using AJAX

I'm trying to figure out how to change behaviour of a button using AJAX.
When the button is clicked, it means that user confirmed order recently created. AJAX calls /confirm-order/<id> and if the order has been confirmed, I want to change the button to redirect to /my-orders/ after next click on it. The problem is that it calls again the same JQuery function. I've tried already to remove class="confirm-button" attribute to avoid JQuery again but it does not work. What should I do?
It would be enough, if the button has been removed and replaced by text "Confirmed", but this.html() changes only inner html which is a text of the button.
$(document).ready(function () {
$(".confirm-button").click(function (b) {
b.preventDefault();
var $this = $(this);
var id = this.value;
var url = '/confirm-order/'+id;
$.ajax({
type: 'get',
url: url,
success: function (data) {
$this.empty();
$this.attr('href','/my-orders/');
$this.parent().attr("action", "/my-orders/");
$this.html('Confirmed');
}
})
});
});
The event handler will be still attached to the button, so this will run again:
b.preventDefault();
which will prevent the default, which is opening the href. You need to remove the event handler on success. You use the jQuery #off() method:
$(".confirm-button").off('click');
or more shortly:
$this.off('click');
You can add to your success function something like: $this.data('isConfirmed', true);
And then in your click handler start by checking for it. If it's true, redirect the user to the next page.
$(".confirm-button").click(function (b) {
b.preventDefault();
var $this = $(this);
if ($this.data('isConfirmed')) {
... redirect code ...
}
else {
... your regular code ...
}
}
You need to use .on() rather than .click() to catch events after the document is ready, because the "new" button appears later.
See http://api.jquery.com/on/
$(document).ready(function() {
$('.js-confirm').click(function(){
alert('Confirmed!');
$(this).off('click').removeClass('js-confirm').addClass('js-redirect').html('Redirect');
});
$(document).on('click', '.js-redirect', function(){
alert('Redirecting');
});
});
<button class="js-confirm">Confirm</button>

Using $(this) inside a jQuery AJAX callback

I have been all over Stack Overflow looking for a solution and none seem to work.
I cannot seem to figure out the issue. I have a button inside a <td> and on clicking it I want to make an AJAX call to update a database and upon success of that AJAX call I want to update the class of the <td> to mark the button as clicked.
I have tried var that = this; in the function. I've tried context: this, in the callback.
function setScoreA(event,candidate,rubric,category,score){
var author = document.getElementById("author").value;
if(author != ""){
$.ajax({
context: this,
type: "POST",
url: "stressBoardUpdate.php",
data: "candidate="+candidate+"&category="+category+"&score="+score+"&author="+author,
success: function(){
$(that).parent('td').siblings().removeClass('isScore');
$(that).parent('td').addClass('isScore');
}
});
}else{
alert("Author must contain something...");
}
}
Here is how the function would get invoked.
<input type="button" "="" value="5" onclick="setScoreA('Stress Board','Y235','Stress Board Rubric','Handled Stress','5');">
onclick="setScoreA does not set this to the element clicked but rather to window. The way you are using it. The way you are using it, I'm not sure that you could actually get a reference to the element. Instead of using onclick, you should bind an event listener (which you can do with jQuery anyway):
$("input").on("click", function () {
setScoreA(this, 'Stress Board','Y235','Stress Board Rubric','Handled Stress','5');
});
function setScoreA(element, ...
/* snip */
context: element
If you really wanted to stick with this for some reason, you could use:
setScoreA.call(this, 'Stress Board' ...
First of all, make use data attributes in your code and setup a common .click() listener
HTML:
<input type="button" class=".button-group" data-event="Stress Board" data-candidate="Y235" data-rubric="Stress Board Rubric" data-category="Handled Stress" data-score="5">
jQuery:
$(".button-group").click(function() {
// Do something
});
Also, I presume you are dynamically generating many buttons. The code above could be improved having only 1 click listener for the whole table, rather setting up a click listener for each item.
$("#wrapper").on("click", "input", function() {
var event = $(this).data("event");
var candidate = $(this).data("candidate");
var rubric = $(this).data("rubric");
var category = $(this).data("category");
var score = $(this).data("score");
setScoreA(this, event, candidate, rubric, category, score);
});
JSFIDDLE DEMO
Resources:
.data()
.click()
.on()

AJAX/JQUERY Can't seem to delete data

Well my main problem is the button. I can't seem to find the reason why the button doesn't show up when I already clicked a certain tr
Here is the code that displays the returned employee data from the database
$.each(data, function(index, val) {
$("#employee_list").append('<tr class="emp_delete" id="'+val.emp_id+'"><td>'+val.emp_id+'</td><td>'+val.last_name+'</td><td>'+val.first_name+
'</td><td>'+val.middle_in+'</td>'+
'<td><input type="button" value="Resigned Employee" class="deleteBtn" id="delete_"'+val.emp_id+'"></td></tr>');
});
and here is the code that shows the button if .emp_delete is clicked. then the .deleteBtn code to delete the certain data
$(".emp_delete").click(function(){
var ID=$(this).attr('id');
$("#delete_"+ID).show();
});
$(".deleteBtn").click(function(){
var ID=$(".emp_delete").attr('id');
if (confirm("Are you sure you want to delete?")) {
var dataString = 'emp_id='+ID;
$.ajax({
type: "POST",
url: "<?php echo site_url('c_employee/delete_employee'); ?>",
data: dataString,
cache: false,
success: function(html){
location.reload();
}
});
}
UPDATE
The code that #Satpal gave worked but the .deleteBtn still doesn't show up after going through the each loop.
Here is the updated code:
$('#employee_list').delegate( ".emp_delete", 'click', function() {
var ID=$(this).attr('id');
$("#delete_"+ID).show();
});
$(".deleteBtn").click(function(){
var ID=$(".emp_delete").attr('id');
if (confirm("Are you sure you want to delete?")) {
var dataString = 'emp_id='+ID;
$.ajax({
type: "POST",
url: "<?php echo site_url('c_employee/delete_employee'); ?>",
data: dataString,
cache: false,
success: function(html){
location.reload();
}
});
}
else
return false;
});
As you are adding HTML dynamically.
You need to use Event Delegation. You have to use .on() using delegated-events approach.
Use
$(document).on(event, selector, eventHandler);
In above example, document should be replaced with closest static container.
In Your case
$('#employee_list').on('click', ".emp_delete", function() {
var ID=$(this).attr('id');
$("#delete_"+ID).show();
});
Similarly you have to delegate event for ".deleteBtn"
Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time.
EDIT
As per comment.
Since you are using jQuery 1.5, use .delegate()
$(elements).delegate( selector, events, data, handler );
In Your case
$('#employee_list').delegate( ".emp_delete", 'click', function() {
var ID=$(this).attr('id');
$("#delete_"+ID).show();
});
EDIT 2
Use similar syntax for delete button also
$('#employee_list').delegate( ".deleteBtn", 'click', function() {
});
You mean the button does not fire?
If so, that is because you define the function before you insert the element in the DOM, you need to bind it.
So instead of:
$(".deleteBtn").click(function(){
Put:
$("#employee_list").on("click",".deleteBtn",function(){
Once the document has been fully loaded, each time you add a new object to the DOM dynamically (like adding a new table row with buttons) you'll need to bind the generated element to an event or action, you cannot say "do something when someone clicks any button" you'd say "do something when someone clicks THIS button" meaning that you have to have the object created first in order to "attach" some action to it.
So let's say that you have these:
<button class="action-button" id="1">Button 1</button>
<button class="action-button" id="2">Button 2</button>
And then this javascript:
$(document).ready(function(){
$(".action-button").click(function(){
alert('My id is ' + $(this).attr('id'));
});
});
And then you later decide to add a button with some action on your js/html:
<button class="action-button" id="3">Button 3</button>
Surprise! If you click button 3 you'll get no alert...? Why, because the function that you set up for click event on document.ready parsed only the initial two buttons that existed at that moment, but since you added a third one dynamically later, the document.ready code wasn't aware of it.
So as Emil pointed out, each time you create a new element you'll want to bind it, in our example, for our button 3:
$('#3').bind('click', function(){
alert('My id is ' + $(this).attr('id'));
});
Or by the class, which is not adequate cause it would rebind existing elements and you lose performance:
$('.action-button').bind('click', function(){
alert('My id is ' + $(this).attr('id'));
});
So make sure that if you add elements that do actions or call functions you bind them when you add them, ideally, have a separate function which does whatever the button needs to do and then when you bind the new element, bind it to that function instead of putting a direct callback.
Try jquery version less than 1.9:
$('selector').live('click', function(){
});
you have a problem with the id delete
<div id="di"></div>
Algo
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script type="text/javascript">
$('#algo').click(function(){
var a = 1;
//THIS IS IMPORTANT , SEE ID = "delete_" <- has a problem
$('#di').html('<td><input type="button" value="Resigned Employee" class="deleteBtn" id="delete_'+a+'"></td></tr>');
});
</script>
Is id="delete_'+val.emp_id+'" and not id="delete_"'+val.emp_id+'" (" <- error)

Mouseover event in jQuery

I have the following mouseover function:
$('.msg_id').live("mouseover", function() {
$(this).css('cursor', 'pointer');
tid = $(this).attr('id');
idx = $(this).attr('name');
resp="";
$.ajax({
async: false,
url: "log_msg.asp",
data: $("#msgForm").serialize() + "&aktion=popup&msg_id="+tid+"&msg_id"+idx,
success: function(data){
$("#"+tid).html(data);
}
});
//$.post("log_msg.asp", $("#msgForm").serialize() + "&aktion=popup&msg_id="+tid+"&msg_id"+idx,
//function(data) {
//}).success(function(){
//$("#"+tid).html(data);
//resp=data;
//$('#bub'+tid).css('display', 'block');
//popd.css('display', 'block');
//});
});
It puts some html code inside .msg_id ( $("#"+tid).html(data); ).
The function mouseover is called in a loop. The ajax request is sent all the time while mouseovering it, not only once.
How can I fix it?
I have also tried mouseenter, but it fires in a loop too.
You might want to use the mouseenter() event instead, as mouseover will fire upon every move inside the element.
$('.msg_id').live("mouseenter", function() {
//Do work here
});
or if live isn't required, simply:
$('.msg_id').mouseenter(function() {
//Do work here
});
MouseOver():
Will fire upon entering an element can fire inside of any child elements.
MouseEnter():
Will fire upon entering an element, and only that element.
You want to use mouseenter

Categories