Closing a dynamically created jQuery-ui dialog - javascript

I am creating a user information edit dialog that fetches edit-user information using $.post but I'm unable to close this dialog since dialog wasn't initialized using any HTML element.
I am trying $('#editUser').dialog('close') but it won't work.
Here is the main body:
<div id='userInfo'>
<div class='user'>
<span class='userId'>1</span>
<span class='userName'>John</span>
</div>
<div class='user'>
<span class='userId'>2</span>
<span class='userName'>Jane</span>
</div>
and here is the script used to create the dialog:
$(function() {
$('.user').click(function() {
var uid = $(this).find('span.userId').html();
$post('/e-val/user/edit.php', {id: uid}, function(html) {
$(html).dialog();
});
});
$('body').on('click', '#closeEditDialog', function() {
$('#editUser').dialog('close')
});
});
The dialog opens up fine as expected but isn't closing as it should.
This is the HTML for the dialog as returned by the ajax script.
<div id='editUser'>
<table>
<tr>
<td>Username</td>
<td><?php echo $user['name'] ?></td>
</tr>
<tr>
<td>Email</td>
<td><?php echo $user['email'] ?></td>
</tr>
<tr>
<td colspan='2'>
<input type='button' id='closeEditDialog' value='close' />
</td>
</tr>
</table>
</div>
What can I do to close it? I can use $('#editUser').remove() to remove the dialog, but I need to close it not remove it.

var mydialog;
$(function() {
$('.user').click(function() {
var uid = $(this).find('span.userId').html();
$post('/e-val/user/edit.php', {id: uid}, function(html) {
mydialog = $(html);
mydialog.appendTo('body');
mydialog.dialog();
});
});
$('body').on('click', '#closeEditDialog', function() {
mydialog.dialog('close')
});
});

You might need to insert that html into your DOM before creating your dialog.
$("body").append(html);
$("#editUser").dialog();
Well at least if your dialog shows up this way, there is nothing preventing it from closing, you're using the same selector.
EDIT
Also, do not forget that .dialog() will initialize the widget, try not calling it more than once. Using .dialog("open") instead.
Best would be even to already add the dialog's div into your html, and then append your server side code in it to dynamically update the content of the dialog.

$('#editUser').dialog('close') won't work because you've never used $('#editUser') to initialize the dialog, so you cannot use it either to close it, You need to use the same handler that was used to create it.
As answered here by Gil & Trinh :
Just add the dialog content to the DOM first and then initialize the dialog:
$post('/e-val/user/edit.php', {id: uid}, function(html) {
$(html).appendTo('body');
$('#editUser').dialog( {autoOpen: false} );
});
autoOpen: false will prevent the dialog from opening by itself and it can be opened using $('#editUser').dialog('open') anytime.

Related

How to make button work after ajax called

In my project, I use the seaStBt button to open a search dialog.
I use AJAX to fetch data from the DB after I confirm the search dialog, which contains search conditions, and this data updates the idcCstmRId div successfully.
Here is the js code:
<script>
$(document).ready(function()
{
$('#idcCstmRId').on("dblclick","#bbs td",function(){......});
$('#seaStBt').click(function(){
$('#dlgSea').dialog("open");
});
$('#seaBt').click(function(){
var seaSlt1 = $('#seaSlt1').val();
$.ajax({
dataType:'html',
type:"POST",
url:"get_ajax_csc.php",
data: {seaSlt1:seaSlt1},
success:function(data)
{
$('#idcCstmRId').html(data);
$('#dlgSea').dialog("destroy").remove();
}
});
});
......
}
</script>
Here is html code:
<div id="firDiv">
<?php
echo '<table border=1px style="width:100%" id="bbs">';
.......
?>
<div class="main_title" id="mnTlt">
<input type="button" id="seaStBt" value="search">
</div>
<div id="dlgSea" >
<input type="submit" value="confirm" id="seaBt" />
</div>
<div class="idcCstmRqst" id="idcCstmRId"></div>
Here is get_ajax_csc.php code:
if(isset($_POST['seaSlt1']))
{
include("DB.php");
$seaOne=$_POST['seaSlt1'];
echo '<table border=1px style="width:100%" id="bbs">';
......
}
The problem is before fetching data from the DB, the seaStBt button displays search the dialog. But after fetching data, and idcCstmRId div updates successfully, the seaStBt button does not work any more. The search dialog does not show after clicking the seaStBt button.
Perhaps the AJAX changes the DOM, but seaStBt button sees does not see these changes?
I have no idea, who can help me ?
Problem could be with .remove() method.
jQuery docs says .remove() takes elements out of the DOM, so you are removing #dlgSea...
Are you saying you want to remove the click event from #seaStBt after the results are returned? If so, I believe you can do this with:
$('#seaStBt').unbind('click');

Jquery will not remove div

I have form in which I am adding some dynamic actions. I have a table in which I have rows of positions
applicants applied for. There is an offer postion button and when they click on the offer button I want to insert the offer fields to be submitted and updated. I can get the feilds to insert but when I click on the cancel transaction button, I can't get it to empty the div addapptrans where the form is built. Below is the code. I know it must be something simple I am missing.
<head>
<script type="text/javascript">
$(function(){
$(".offerposition").click(function(){
var row = $(this).closest('tr').find('td:nth-child(1)').text();
alert('You clicked on ' +row);
$("#addapptrans").empty();
$("#addapptrans").append(
$("<input>").attr('type','hidden').attr( 'value',row).attr('Name','Mchposid'))
.append(
$("<input>").attr('type','submit').attr( 'value','Complete Offer').attr('id','completeoffertrx').attr('name','completeoffertrx').addClass("buttonlarge buttonmargin")
).append(
$("<input>").attr('type','button').attr( 'value','Cancel Transaction').attr('id','canceloffertrx').attr('name','canceloffertrx').addClass("buttonlarge buttonmargin")
);
}
)
}
);
$(function(){
$("#canceloffertrx").click(function(){
$("#addapptrans").empty();
})
})
</script>
</head>
<body>
<form >
<div id="addapptrans"></div>
<p class="posttitle">Positions applied For</p>
<table class="tabpositions">
<tbody>
<tr>
<th class="position">Position</th>
<th class="department">Department</th>
<th class="dateapp">Date Applied</th>
<th class="appdate">Offer?</th>
</tr>
<tr>
<td style="display: none;">2281</td>
<td>Building Service Worker - Part time</td>
<td>Environmental Services</td>
<td>08/13/2001</td>
<td><input type="button" class="offerposition" value="Offer Position"></td>
</tr>
</tbody>
</table>
</form>
This code here:
$(function(){
$("#canceloffertrx").click(function(){
$("#addapptrans").empty();
})
})
Runs before #canceloffertrx exists on the page. So $("#canceloffertrx").click(fn) Matches zero elements on the page, and binds a click handler to all zero of them.
You can fix this by binding the click handler to the document, or closest parent that is present, instead.
$('#addapptrans').on('click', '#canceloffertrx', function(){
This says that when the element #addapptrans receives a click event, and element that matches the selector #canceloffertrx was the one that was actually clicked, fire the event handler function.
Or by binding the click handler when you create the button.
$("<input>")
.attr('type','submit')
.attr( 'value','Complete Offer')
.attr('id','completeoffertrx')
.attr('name','completeoffertrx')
.addClass("buttonlarge buttonmargin")
.click(function() { ... });
Lastly, some style advice :) Especially when chaining jQuery methods, you can put each call on it's own line which makes it much more readable.
And you should also know that attr() can accept an object as an argument, allowing to call it just once to set many attributes.
$("<input>")
.attr({
type: 'submit',
value: 'Complete Offer',
id: 'completeoffertrx',
name: 'completeoffertrx'
})
.addClass("buttonlarge buttonmargin")
.click(function() { ... });

jquery AJAX call only works once?

I'm setting up some sort of small form to determine whenether my users want to submit a form anonymously or not, and whenether the content they're submitting is original or not.
The first AJAX call seems to work fine, but then when the new content is loaded from a PHP file through AJAX, then the jQuery function doesn't seem to work.
It is supposed to work like this.
They are presented with 2 options, submit with username, or submit anonymously (clicking either of these calls an AJAX request to the specified PHP file)
The PHP file contains another 2 options (see example below) called Original and Existing. (Clicking any of these doesn't seem to do anything!)
Finally, they should be presented with the specific submission form for their choices.
Here is my code:
jQuery
// User
$('#user-submission').on( "click", function() {
$.ajax({url:'<?php echo get_template_directory_uri(); ?>/submission/user-submission.php',success:function(result) {
$("#submit-section").html(result).fadeIn('slow');
}});
});
// Anonymous
$('#anonymous-submission').on( "click", function() {
$.ajax({url:'<?php echo get_template_directory_uri(); ?>/submission/anonymous-submission.php',success:function(result) {
$("#submit-section").html(result).fadeIn('slow');
}});
});
// User -> Original
$('#original-submission-user').on( "click", function() {
$.ajax({url:'<?php echo get_template_directory_uri(); ?>/submission/original-user-submission.php',success:function(result) {
$("#submit-section").html(result).fadeIn('slow');
}});
});
// User -> Existing
$('#original-submission-anonymous').on( "click", function() {
$.ajax({url:'<?php echo get_template_directory_uri(); ?>/submission/original-anonymous-submission.php',success:function(result) {
$("#submit-section").html(result).fadeIn('slow');
}});
});
// Anonymous -> Original
$('#existing-submission-user').on( "click", function() {
$.ajax({url:'<?php echo get_template_directory_uri(); ?>/submission/existing-user-submission.php',success:function(result) {
$("#submit-section").html(result).fadeIn('slow');
}});
});
// Anonymous -> Existing
$('#existing-submission-anonymous').on( "click", function() {
$.ajax({url:'<?php echo get_template_directory_uri(); ?>/submission/existing-anonymous-submission.php',success:function(result) {
$("#submit-section").html(result).fadeIn('slow');
}});
});
Main HTML
<section id="submit-section">
<div class="anonymous-or-credited">
<a href="#" id="user-submission" class="submit-url">
<div class="transition">
<h2><?php echo $current_user->display_name; ?></h2>
<h3>Submit a as <?php echo $current_user->display_name; ?></h3>
</div>
</a>
<a href="#" id="anonymous-submission" class="submit-url">
<div class="transition">
<h2>Anonymous</h2>
<h3>Submit a Creepypasta Anonymously</h3>
</div>
</a>
</div>
</section>
PHP file containments
<div class="anonymous-or-credited">
<a href="#" id="original-submission-user" class="submit-url">
<div class="transition">
<h2>Original</h2>
<h3>I wrote this myself</h3>
</div>
</a>
<a href="#" id="exisiting-submission-user" class="submit-url">
<div class="transition">
<h2>Existing</h2>
<h3>I found this elsewhere</h3>
</div>
</a>
</div>
If the elements are added dynamically, selecting for the ID of the dynamically-added element will not work. You will have to instead listen for event to bubble up in a location higher up (in terms of hierarchy) on the DOM tree, like document.
I assume that both #user-submission and #anonymous-submission are already present on the page when it is initially loaded, but the rest are not. Therefore, you need to listen to the click event bubbling up to document (or any parent that is already present on the page when JS is executed):
$(document).on('click', '#original-submission-user', function() {
$.ajax({url:'<?php echo get_template_directory_uri(); ?>/submission/original-user-submission.php',success:function(result) {
$("#submit-section").html(result).fadeIn('slow');
}});
});
Remember to repeat this for all dynamically-added elements which you want to bind events to.
If I'm understanding correctly, you have JS bindings to HTML that exists on page load -- but when you dynamically load more HTML, your existing JS isn't bound to it. One solution would be to add your click bindings to the ajax callback, after the HTML is loaded.
You need to enter the second parameter of the .on() function (delegated event):
$('#submit-section').on('click','#original-submission-user', function() {
});

complex jquery selector : challenge

I've searched among jquery selectors for some time now, but can't find any solution to my problem.
I've got an html table filed by a foreach. On each line, several links that pop up tooltips. My problem : can't find the right selector.
<table>
<?php foreach($article) :?>
<tr>
<td>
<div class="none" style="display:none;">
<div class="tooltip_1">
"The content of my tooltip_1"
</div>
<div class="tooltip_2">
"The content of my tooltip_2"
</div>
</div>
<div class="cell">
a link
a link
</div>
</td>
<tr>
<?php endforeach; ?>
</table>
To show my tooltip, I use qTip, and it works like this :
$('a[class="link_to_tooltip_1"]').qtip({
content: $('jquery selector'),
(... other options)
});
So basicaly, I would need something like
content: $('self.parentNode.parentNode > div[class="none"] > div[class="tooltip_1"]'),
in other words :
start from link "link_to_tooltip_1"
go back to parent div "cell"
go back to parent td
then go to child div "none"
and finally select child div "tooltip_1"
Thanks a lot.
// this is "complex" version;
// assumes .cell and .none are nested inside same container, whether <td> or <li> or anything
$(".link_to_tooltip_1").each(function () {
console.log($(this).closest(".cell").siblings(".none").find(".tooltip_1"));
// $(this).qtip({ content: /* use above selector */ });
});
// this is the "not-so-complex" version;
// assumes both items are nested arbitrary level deep inside same <td>
$(".link_to_tooltip_1").each(function () {
console.log($(this).closest("td").find(".tooltip_1"));
// $(this).qtip({ content: /* use above selector */ });
});
jsFiddle Link
$('a.link_to_tooltip1').closest('tr').find('.tooltip_1');
is probably what you're seeking for ?
why not place your tooltip like this ? :
<table>
<?php foreach($article) :?>
<tr>
<td>
<div class="cell">
<span class="tooltip_1" style="display:none;" >"The content of my tooltip_1"</span>a link
<span class="tooltip_2" style="display:none;" >"The content of my tooltip_2"</span>a link
</div>
</td>
<tr>
<?php endforeach; ?>
</table>
and
$('a[class="link_to_tooltip_1"]').qtip({
content: $(this).children("span"),
(... other options)
});
Edit
I didn't know you can't use $(this). So in this context, you can do :
$('a[class="link_to_tooltip_1"]').each(function(){
var content = $(this).prev("span");
$(this).qtip({
content: content,
(... other options)
});
Here is the selector you are looking for:
"td:has(.cell .link_to_tooltip_1) .none .tooltip_1"
Explanations:
You can't go backwards (match an element, and then its parent). However you can select an element and verify that it contains elements that match an other selector:
"td:has(.cell .link_to_tooltip_1)"
This selects the parent <td> of .link_to_tooltip_1. So this does exactly the .link_to_tooltip_1.parentNode.parentNode you described.
Then you just have to select .none .tooltip_1 in the selected <td>:
"td:has(.cell .link_to_tooltip_1) .none .tooltip_1"
So your example code becomes:
$('a[class="link_to_tooltip_1"]').qtip({
content: $("td:has(.cell .link_to_tooltip_1) .none .tooltip_1"),
(... other options)
});
And as you were asking for, this is done with just a jquery selector :-)
I'd try something like this:
add a class to the elements with tooltips and rel attribute with the target class of element holding data
link with tooltip yar!
then in JS
$('a.iHaveATooltip').bind('mouseenter', function(){
$(this).addClass('showingTooltip');
}).bind('mouseleave', function(){
$(this).removeClass('showingTooltip');
}).qtip({
content: function(){ return $('.' + $('.showingTooltip').attr('rel')).html() },
(... other options)
});
it's the only idea I can come with to cheat the lack of support for generic data referencing based on DOM structure. Though can't promise it will work as I don't know the plugin and don't know if passing function as an argument won't collide with how it's implemented - you might have to change the plugin to allow it to accept function as content parameter.
good bye and good luck,
Tom

Toggle data display inside table cell

I have a table that's generated by a normal PHP loop. What I want to do is create a form in the first column of each row that's hidden by default but appears when you click a toggle link in that row.
I can make a normal toggle-able div by creating a CSS id called hidden and setting display: none;. Unfortunately I can't keep creating divs with id=hidden that are automatically associated with the preceding link.
I am pretty inexperienced with both Javascript and CSS, so I've mostly tried to do this by patching together examples but I'm coming up empty. I've read in some places that you can't put divs inside of a table, so maybe I'm going about this all wrong.
Here's an example of what the code does and how I wish it worked, but of course it does not.
<script language="JavaScript" type="text/javascript">
function toggle(id) {
var state = document.getElementById(id).style.display;
if (state == 'block') {
document.getElementById(id).style.display = 'none';
} else {
document.getElementById(id).style.display = 'block';
}
}
</script>
<?php
while($array = mysql_fetch_array($sql))
{
?>
<tr>
<td>
<?php
echo $array['some_data'];
?>
Toggle
<div id="hidden"><?php echo $array['hidden_thing']; ?></div>
</td>
<td>
<?php echo $array['some_other_data']; ?>
</td>
</tr>
<?php
}
?>
Just use a different ID for each row:
<?php
$count = 0;
while($array = mysql_fetch_array($sql)) {
$id = 'hidden' . $count++;
$data = $array['some_data'];
$hidden = $array['hidden_thing'];
$other_data = $array['other_data'];
echo <<<END
<tr>
<td>$data <a href="#" onclick="toggle('$id');>Toggle</a>
<div id="$id">$hidden_thing</div>
</td>
<td>$other_data</td>
</tr>
END;
}
Make it a span instead of a DIV as I think that some browsers don't support divs inside table elements. Also, instead of referring to it by ID, pass in this.nextSibling() to the toggle, using DOM navigation to get the next sibling (which should be the SPAN) to show/hide.
function toggle(ctl) {
var state = ctl.style.display;
if (state == 'block') {
document.getElementById(id).style.display = 'none';
} else {
document.getElementById(id).style.display = 'block';
}
}
<a href="#" onclick="toggle(this.nextSibling);">Toggle
</a><div><?php echo $array['hidden_thing']; ?></div>
EDIT: As #tomhaigh suggests (and as shown in the example), for this to work you need to make sure that there is no text/whitespace between the anchor and the div. You could also write a function that, given a DOM element, would select the next non-text DOM element and return it. Then pass this to that function and the result to your toggle function.
Here's my recommended (general solution) using jQuery to reference events relatively instead of maintaining ids for each row and form. This also allows you to hide non-active row forms easily, which is a good idea since only one form can be submitted at a time.
HTML:
<table id="tableForms" class="table">
<tr>
<td class="rowForm"><form><span>form1 content</span></form></td>
<td class="showRowForm">click on row to show its form</td>
</tr>
<tr>
<td class="rowForm"><form><span>form2 content</span></form></td>
<td class="showRowForm">click on row to show its form</td>
</tr>
<tr>
<td class="rowForm"><form><span>form3 content</span></form></td>
<td class="showRowForm">click on row to show its form</td>
</tr>
</table>
Javascript:
<script type="text/javascript" src="/assets/js/jquery.min.js"></script>
<script type="text/javascript">
//as soon as the DOM is ready, run this function to manipulate it
$(function() {
// get all tr elements in the table 'tableForms' and bind a
// function to their click event
$('#tableForms').find('tr').bind('click',function(e){
// get all of this row's sibblings and hide their forms.
$(this).siblings().not(this).find('td.rowForm form').hide();
// now show the current row's form
$(this).find('td.rowForm form').show();
}).
// now that the click event is bound, hide all of the forms in this table
find('td.rowForm form').hide();
});
</script>
Demo:
A working demo of this can be found here.

Categories

Resources