views:

2314

answers:

6

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"&gt;
    <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>&nbsp;</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

A: 

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");
});
VoteyDisciple
+1  A: 

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....

womp
Thank you womp, but I do have something like that in place. The code above should start with <form method="post"> <input type="hidden" name="cmd" value="submitChangedPassword"> but StackOverflow skips it for whatever reason. I already sent an email to them describing the issue.
MrG
I edited your post. I think you had a "tab" character in there. If you indent text by 4 spaces, the editor picks up on it... but I think the tab character was messing it up somehow. I'll take another look at your post in a minute.
womp
Many, many thanks womp, it seems fine now as I noticed after updating it ;) I've added a form ID as you suggested and hopefully used it correctly (-> please check comments in JS) and the behavior improved (all parameters are now sent correctly). Unfortunately the target is still wrong in IE, Safari, Chrome.
MrG
A: 

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:

  1. Remove generic.js from tpl_overview.tpl
  2. 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!

agvstin
Thank you. I've tried both options, but in both cases the entire page is refreshed in ALL browsers ;( Please be so kind and describe option 1, I might have done something incorrectly there. Many thanks!
MrG
I added the first solution here.Remember you always have to make sure your content is loaded, otherwise selectors will return empty array...This bookmark might come handy to check you are attaching all handlers: http://www.sprymedia.co.uk/article/Visual+Event
agvstin
+1  A: 

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.

Nathan Loding
Thank you Nathan, adding 'action' made the thing work for IE and Firefox. Please note that the real code doesn't have the showFile() stuff (I only implemented this to quickly document the bug). Echoing $_REQUEST['cmd'] doesn't make a difference, the behaviour remains the same.
MrG
A: 

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!

Andy Gaskell
Hey pubb, I enabled the script inspector (http://webkit.org/blog/41/introducing-the-web-inspector/) and had a look at the header, but I don't see anything pointing to the solution (my assumption is that it's a client side error). Please point your browser to http://gbits.org/div/ to see for yourself. Many, many thanks!
MrG
Opening up that page in Safari gave me 4 errors - I think all of them are related to the text before the opening html tag. Can you get those errors cleared up?
Andy Gaskell
Absolutely, they've been caused by the "cheap" echo in example.php, which I disabled now.
MrG
So there's kind of a lot going on. When the request is ?cmd=overview the response is not a full page. If an XMLHttpRequest request comes in for ?cmd=changePassword I would return only the form itself, not an entire page. And lastly, I would only bind the form (your generic.js) when the server responds from the ?cmd=changePassword request. You can do this by attaching to the ajaxSuccess event.
Andy Gaskell
Fixed the full page, return only the form -> both done. Are you sure that it makes any difference if I bind generic.js only on that specific request? It has a lot more stuff in it within the "real" system and my guess would be that if doesn't work if it's always loaded, it won't work either if loaded on certain events.
MrG
My reasoning behind rebinding is that you're not using the live method (http://docs.jquery.com/Events/live) - and live is not supported with submit anyway. The problem is when you bind immediately that form does not exist on the page - you need to bind to the form once it exists.
Andy Gaskell
+1  A: 

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!

MrG