views:

256

answers:

1

I'm combining Tablesorter's 'disable headers using options' function and the 'trigger sortStart / sortEnd' function and have run into an issue. The following code works fine for the most part, BUT: when you click on a disabled header, the progress-indicating #overlay div appears and never goes away.

<script type="text/javascript" id="js">
$(document).ready(function() {
  // call the tablesorter plugin, the magic happens in the markup
  $("#projectTable").tablesorter({ 
      // pass the headers argument and assing a object 
      headers: { 
          // assign the secound column (we start counting zero) 
          1: { 
              // disable it by setting the property sorter to false 
              sorter: false 
          }, 
          // assign the third column (we start counting zero) 
          2: { 
              // disable it by setting the property sorter to false 
              sorter: false
          } 
      } 
  });

  //assign the sortStart event
  $("#projectTable").bind("sortStart",function() {
      $("#overlay").show();
  }).bind("sortEnd",function() {
      $("#overlay").hide();
  });
}); </script>

Any ideas on how I could fix this so that nothing at all happens when the disabled headers are clicked? Thanks!

+1  A: 

EDIT:

This is a solution using some modifications I made to the plugin. The nature of the plugin was such that you can't know which header was clicked (which seems very strange to me). I'll post the changes I made if you would like.

   // Works only with plugin modification
$("#projectTable").bind("sortStart",function(e) { 
    if( $(e.target).hasClass('header') ) {
        $("#overlay").show();
    }
}).bind("sortEnd",function(e) {
    if( $(e.target).hasClass('header') ) {
        $("#overlay").hide();
    }
});

EDIT:

Here are the changes I made to the plugin:

Just to give a little background, sortStart and sortEnd are custom events bound to the table. In the plugin, a click event is bound to the headers, which in turn triggers the sortStart custom event on the table. Because of this, there is no reference in the callback to the actual element that received the click.

The sortEnd is just triggered a little further down in the same click event for the headers.

I don't know why the author did it this way, but then again, I don't know why the author used a common word like "header" to denote the header elements. That's just asking for trouble.

Anyway, here are the fixes. I'm going to give line numbers from the latest unminified version of the plugin.


Step 1:

Around line 520 you'll see this code where the click is set up for the headers:

// apply event handling to headers
// this is to big, perhaps break it out?
$headers.click(function(e) {

    $this.trigger("sortStart");

...change it to this:

// apply event handling to headers
// this is to big, perhaps break it out?
$headers.click(function(e) {

    $(e.target).trigger("sortStart"); // e.target refers to the clicked element.
                                      // The event will bubble up to the table, 
                                      //    and fire.

Step 2:

Then a little further down around line 578 you'll see this code:

setTimeout(function() {
    //set css for headers
    setHeadersCss($this[0],$headers,config.sortList,sortCSS);
    appendToTable($this[0],multisort($this[0],config.sortList,cache);
},1);

...change it to this:

setTimeout(function() {
    //set css for headers
    setHeadersCss($this[0],$headers,config.sortList,sortCSS);

      // Passes the element clicked to appendToTable() ------------------v
    appendToTable($this[0],multisort($this[0],config.sortList,cache), e.target);
},1);

Step 3:

Then go to the appendToTable() function around line 243 where you'll see:

function appendToTable(table,cache) {

...change it to:

  // Receives element we passed --------v
function appendToTable(table,cache,theHeader) {

Step 4:

Finally, in the same appendToTable() function, around line 285 you'll see this:

setTimeout(function() {
    $(table).trigger("sortEnd");    
},0);

...change it to:

setTimeout(function() {
       // Triggers the sortEnd event on the element we passed in
    $(theHeader).trigger("sortEnd");    
},0);

Again, I don't know if there will be any side effects. I sort of doubt it, though. Give it a shot, and let me know how it turned out for you.

patrick dw
Thanks Patrick! Unfortunately both of those options turn off turn off the #overlay altogether so it never shows, even when it's supposed to.
McGirl
@McGirl - Any chance that the headers have any child elements?
patrick dw
@McGirl - I've been tinkering with tablesorter, and I'm having trouble with the event object. Digging deeper...
patrick dw
@McGirl - Well, I got it to work, but only after making some modifications to the plugin to pass the header that was clicked into the callback for the custom events (sortStart and sortEnd). If you want to use a modified version of tablesorter, I'd be happy to show you the changes I made.
patrick dw
I'd love to see the plugin changes - thanks for spending so much time on this! It is amazing how long this plugin has been around with this pseudo-bug. I'm sure many people would appreciate your update, I found others on the web who were having the same issue but no solutions.
McGirl
@McGirl - Sure, I'll modify my answer with the changes. Just be aware that I haven't tested it in depth. Only enough to make sure that the callbacks work, so use at your own risk. ;o)
patrick dw
Thanks again @Patrick!!! I followed your changes and they all make sense, but unfortunately I'm still seeing no overlay div pop up when I click the headers. I've triple-checked to make sure I'm using all the code you supplied correctly, and I tried debugging but all that tells me is that the overlay div isn't being triggered. I'm trying to learn more jQuery but this is beyond me - I can't tell you how much I appreciate your help.I've uploaded the changes you suggested to my test site in case that helps in diagnosing the issue: http://wwwtest.utexas.edu/ssw/cswr/projects/project-list/
McGirl
@McGirl - After taking a look at your source, it appears as though you have 2 different versions of jQuery being loaded (both outdated). Version 1.2.3 from 2008 and version 1.3.2 from 2009. This may cause problems. Not sure though. The most recent version is 1.4.2. You could that instead, just note that when I loaded the tablesorter plugin with 1.4.2, I had some other error that I had to get around, so you may need to go back to 1.3.2. Looks like you did the updates properly. See about removing the oldest jQuery, and let me know how it turns out. :o)
patrick dw
@McGirl - ...additionally, I see that the older jQuery version is loaded after the newer version (and is therefore likely overriding the newer). The older one doesn't allow custom events to bubble, but 1.3.2 does. So that's the first thing I'd try. The file name of the older one is (ironically) `jquery-latest.js`. :o)
patrick dw
Ha! The jquery-latest.js is what came with the Tablesorter plugin. I've removed it so that the page uses v 1.3.2, but that breaks everything this plugin does. It's like it's not calling jQuery at all. Is there a setting I need to change maybe? Thanks @Patrick!
McGirl
@McGirl - The error I'm getting is `Uncaught TypeError: Property '$' of object [object DOMWindow] is not a function`. This usually happens when you don't have jQuery, or when something redefines the variable `$`. Try using Google's hosted jQuery instead to see if it improves things: `<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>`
patrick dw
@McGirl - Ah, I see the issue. The current jQuery file you're using calls `jQuery.noConflict()` at the end. This causes jQuery to give up control of the `$` variable. It is something you do when you are using another library that also uses the `$` variable. If you delete that line, I'll bet things will start working.
patrick dw
@Patrick you are a rockstar. Thank you so much, that was exactly it. Deleted the noConflict and voila. Because that's the default jQuery file that comes with WordPress, however, I got concerned that any WP upgrade would add the noConflict back in. I found this wrapper (http://codex.wordpress.org/Function_Reference/wp_enqueue_script#jQuery_noConflict_wrappers) which gets around that issue. I've added it to my function to get everything working despite the noConflict call in jquery.js. Again, THANK YOU so much for your help!
McGirl
@McGirl - Ah, very good. Glad to see you got things working. :o)
patrick dw