views:

709

answers:

3

Hello,

I have been trying to get this working for the last 7 hours so please excuse the slight tone of frustration.

I have successfully implemented a nice set of jquery ui tabs that load their content via ajax.

The content loaded via ajax features a form. I wanted the first field in the form (which has an ID of #title) to be focused automatically when the tab is loaded. This didnt work when I tried putting the script in the external document so I thought a callback would be a good idea.

setTimeout( function() { $("#title").focus(); }, 500 );

I got this idea from here. The delay is because i was experiencing problems with the field not focusing properly when clicking through each tab. At first I thought this had solved some of the problem, however after even more testing I found that this focus field works only on the tab that was initially loaded.

I decided to clear my head and implement a nice jquery autocomplete text field.

This script seemed to work when loaded straight into the external content, but to my dismay further testing showed this not to be the case. The autocomplete field works only on the tab that is loaded when the page is loaded.

This is when I noticed the pattern that both my scripts are only working on the initial loaded tab.

I have tried using the select, load and show events but all fail to work.

I know the callback is working because the alert is appearing when each tab is clicked.

Obviously I am doing something very wrong.

Please pick my code to pieces and tell me what I am doing wrong.

<script type="text/javascript">
 $(function() {
  $("#tabs").tabs({
   load: function(event, ui) { setTimeout( function() { $("#title").focus(); }, 500 );
    $("#role").autocomplete(
     "/profile/autocomplete",
     {
      delay:10,
      minChars:1,
      matchSubset:1,
      matchContains:1,
      cacheLength:10,
      onItemSelect:selectItem,
      onFindValue:findValue,
      formatItem:formatItem,
      autoFill:true
     }
    );

   alert('callback');
    }
   });

  });
 </script>
A: 

Not 100% sure, but it may be because you wrap your handling code in $(document).ready(function() { ... });.

Marcelo Cantos
I have removed the above code, deleted cookies and cleared the cache. Unfortunately the issue remains.
Tim
+1  A: 

Your problem is not entirely clear from the question. I would say the $(document).ready part is definitely not needed but probably wouldn't cause any problems since I think it will run immediately.

What I'm not sure about is how you are creating your tabs and particularly what you mean by "only on the first tab load, loading another tab doesn't focus the field." What exactly do you mean by load? Are the tabs being loaded via an Ajax call or do you just mean as the page renders? Do you want a specific element to be focused PER tag, or just every time a tag is loaded? (Your code says one specific field but your text is unclear).

Ok, based on your clarifications, I realize now the problem is that you have multiple instances of 'title' and 'role' but you are using IDs to name and reference them. In the html, you have something like this

<div id="tabs">
    <div class="tab">
        <input id="title">
        <input id="role">
    </div>
    <div class="tab">
        <input id="title">
        <input id="role">
    </div>
    ...
    etc
</div>

The problem is, the 'id' field has to be unique across all your elements, otherwise you can only refer to one of them (not just unique per tab). So when you say $('#title'), you are only able to refer to the first element with an id of 'title'. Many people solve this problem by adding numbers and giving ids to the tabs of 'tab1', 'tab2', etc and the 'title1', 'title2', etc. This is actually a bad idea with jquery. You should instead use classes and the very useful jquery .find() method like this:

<script type="text/javascript">
    $(function() {
        $("#tabs").tabs({
            load: function(event, ui) {
                var tab_content = $(ui.panel);
                setTimeout( function() { tab_content.find(".title").focus(); }, 500 );
                tab_content.find(".role").autocomplete(
                    "/profile/autocomplete",
                    {
                        delay:10,
                        minChars:1,
                        matchSubset:1,
                        matchContains:1,
                        cacheLength:10,
                        onItemSelect:selectItem,
                        onFindValue:findValue,
                        formatItem:formatItem,
                        autoFill:true
                    }
                );
                alert('callback');
            }
        });
    });
</script>

Still not sure if the timout on the focus is necessary. You should remove that if it was just an attempt to 'make something work'.

Rob Van Dam
Rob,I deeply appologies for the poorly worded question. I went back through and added important details i just completely forgot about.The tabs are just standard JQUERY UI tabs that load their content in via ajax. Each tab loads in a standard form that I wanted to have the first field (#title) to be automatically focused. This only works on the tab that was loaded with the page. Clicking on the other tabs loads the form, but the #title field is not focused. Same problem with my other script. I have tried show, select and load events however all fail to fix this problem.
Tim
Ah, that confirms what I suspected. I've edited my question to reflect your comment.
Rob Van Dam
Thanks for all your help Rob. Wish i could share the bounty
Tim
+1  A: 

I believe the problem is you don't have unique IDs. If your HTML is similar to this:

<div class="tabs">
 <ul>
  <li><a href="tab1.htm">Tab1</a></li>
  <li><a href="tab2.htm">Tab2</a></li>
 </ul>
</div>

The Tab plugin will load both of the pages (tab1.htm and tab2.htm) into the current page. And since the first tab has both #title and #role jQuery stops searching for a duplicate (rightly so). So, the easy solution would be to make them classes, then have the show function target the selected tab and call the focus and autocomplete plugin.

$(function(){
 $(".tabs").tabs({
  show: function(e, ui) {
   $(ui.panel)  // target the current tab contents
    .find('.title').focus().end()
    .find('.role').autocomplete(
      "/profile/autocomplete",
      {
       delay:10,
       minChars:1,
       matchSubset:1,
       matchContains:1,
       cacheLength:10,
       onItemSelect:selectItem,
       onFindValue:findValue,
       formatItem:formatItem,
       autoFill:true
      }
     );
  }
 });
});

And to answer a question you had in a comment, a callback is basically what you want to happen after whatever you were doing is complete. For example, the function below will hide the element with the class hideme then once the fadeOut effect is complete, the callback function removes the element from the page (and DOM)

$('.hideme').fadeOut('slow', function(){
 $(this).remove();
})

Also, in case you aren't familiar with .end() it allows you to chain objects. More specifically it reverts the selector back to the most recent object which in this case is ui.panel. Read more about it here and also be sure to check out .andSelf() here.

fudgey
Thanks fudgey for that. That solved my problem. Wow a valuable reminder of the difference between classes and ID's. I really appreciate the extra information you have put at the bottom of your answer. I will definitely read up and learn more about the DOM and callbacks!
Tim