I'm referring to a problem similar to the one in this post, because the solution described there doesn't work for me.
The starting point is a HTML page (called profile) with jQuery UI tabs:
<div id="tabs">
<ul>
<li><a href="#realtab">Foo Bar</a></li>
<li><a href="?cmd=changePassword" title="pwd-settings">
<span> Dynamic tab </span>
</a></li>
</ul>
</div>
The HTML rendered within the DIV is:
<form method="post" id="subform" action="http://myhost.com/example.php">
<input type="hidden" name="cmd" value="submitChangedPassword">
<dl>
<dt>PWD1</dt>
<dd><input type="password" name="password" /></dd>
<dt>PWD CHK</dt>
<dd><input type="password" name="passwordChk" /></dd>
<dt> </dt>
<dd><input type="submit" value=" Apply " /></dd>
</dl>
</form>
In addition, I use the following JS script (based on the post linked in the introduction):
$('#subform').submit(function() { // catch the form's submit event - should I use the form id?
$.ajax({ // create an AJAX call...
data: $(this).serialize(), // get the form data
type: $(this).attr('method'), // GET or POST
url: $(this).attr('action'), // the file to call
success: function(response) { // on success..
$('#pwd-settings').html(response); // update the DIV - should I use the DIV id?
}
});
return false; // cancel original event to prevent form submitting
});
The record is submitted, but the behavior is different depending on the browser:
IE, Firefox, Opera: correct content into DIV, excellent!
Safari, Chrome: correct content, but the entire page is refreshed with the results
Please let me know what I'm doing wrong. Many many thanks!
UPDATE 1: The DIV named pwd-settings is created by the tab interface only. Please note that the behavior is the same, even if I add it to the HTML (with <div id ="pwd-settings"></div>
).
UPDATE 2: I also removed the JavaScript above and all browsers became "correct content, but the entire page is refreshed" = "old URL, new content". As soon as I added the JavaScript to the HTML page rendered within the DIV, it started working in the browser described above. Hence I see two possible error reasons:
1) The JS is simply not executed in the browsers having errors or
2) The JS within the DIV doesn't work because it addresses a DIV which only exists outside
The easiest way to solve this would be to add a hidden input to your form:
<input type="hidden" name="cmd" value="checkPassword" id="cmd-field" />
If this value needs to change depending on which tab is showing (though it doesn't sound like that's the case), you can change it dynamically when the tab is toggled:
$("#invent-an-id-for-the-link-that-switches-to-this-tab").click(function() {
$("#cmd-field").value("checkPassword");
});
jQuery's serialize() function only gets <input>
elements. A link element is not an input. Calling $(this).serialize()
won't add the value of the <a>
element to your data.
You need to add an <input>
element to hold that data. Perhaps try
<input type="hidden" value="changePassword" name="cmd" />
EDIT: Can you post the full html? From the looks of it right now, your selectors won't select the form because it doesn't even have an id property....
Looks like you're handler is not being loaded for the latter browsers... Since the content of the form is dynamic you've gotta make sure is loaded into the DOM before setting the form's handler.
You have 2 possible solutions.
First, once the tab content is loaded, load the piece of script you posted (check jquery doc for tab event load: http://docs.jquery.com/UI/Tabs#event-load).
Second, use jquery live event on button click (currently event submit is not supported). Check out: http://docs.jquery.com/Events/live
The code for the second solution:
$('#subform input:submit').live('click', function() { // catch the form's submit event - should I use the form id?
$.ajax({ // create an AJAX call...
data: $(this).serialize(), // get the form data
type: $(this).attr('method'), // GET or POST
url: $(this).attr('action'), // the file to call
success: function(response) { // on success..
$('#pwd-settings').html(response); // update the DIV - should I use the DIV id?
}
}); return false; // cancel original event to prevent form submitting });
First solution
These are the changes I made to get it to work:
Change the code (@tpl_overview.tpl):
$(function() { $('#tabs').tabs() });
with this code:
$(function() {
$("#tabs").tabs( {
load: function(event, ui) {
// load specific script to handle form submission
if ($(ui.tab).attr('href') == '#pwd-settings') {
$.getScript('generic.js');
}
}
} );
});
This will load and execute the generic.js script after the content of the tab is loaded.
If you see yourself doing this too many times, perhaps you can name your scripts after the tab link names...
Let us know if it worked!
Here's my guesses --
First, you don't have an 'action' attribute on your form. So the JS line for $(this).attr('action') doesn't return anything. I'm not sure how jQuery Ajax handles that.
But I think the real issue is the example.php script and how it's handling your calls. I'm no Ajax expert, but that is not the way I would do it at all. If you take out the showFile() stuff, and just echo $_REQUEST['cmd'], does it work?
Other than that, I'm out of ideas. But it's not a quirk of the browsers, it's an issue with your code, I can say that much.
Safari has excellent web dev tools. If you're running the Windows version you have to enable it in Preferences -> Advanced. Open up the Web Inspector and check your request/response headers.
This won't point directly to the solution but right now there isn't much to go on. Get those headers and keep us updated!
I finally found out the reason: some browsers (namely the ones having issues) behave differently when the JS described in the question is loaded due to the fact the form does not exist yet because the content of the tab is loaded later on via Ajax.
Hence the solution is to create a JS function instead of the code above and adapt the button (submit becomes button, introducing onClick):
<input type="button" value=" Apply " onClick="callMyFunction()" />
This is handled correctly by Safari and Chrome then too.
Many thanks to all participants!