Defeat click handling in headers

Defeat click handling in headers

atlas3650atlas3650 Posts: 11Questions: 0Answers: 0
edited May 2009 in General
Hi Allan,

By far and away, this plugin is the nicest and best developed jquery plugin of its kind (major, major kudos). Everyone else needs to follow your model (but maybe that don't have as much time! thank goodness you do). Vs jqGrid (nice but hugely complex) and tablesorter (nice but buggy), dataTables is the clear winner.

Now, here's two challenges I have.

I need to put filtering controls into a column header. However, even if a column is set bSortable=false, the code still gets the click. It does a return; if bSortable is false, but I think this eats the event. I tried changing it to return true; (line 1986) but that didn't seem to help, and anyway, I don't want to modify your source. I tried unbinding click on that TH with firebug but still couldn't get it to stop eating clicks. I need a couple divs inside my headers to handle clicks.

The second challenge is probably easier: I need the filter controls I just mentioned do "static filtering", ie, the column in question can only have 3 values and I want the control to let me reduce the table to one of the three as per the user's choice. For instance, the column may have any one of "A", "B", or "C", and the user needs to be able to choose "All", or just the "A"'s, just the "B"'s, or just the "C"'s using clickable divs inside the header of that column. How can I accomplish this?

Thanks very much for this wonderful tool.

Replies

  • atlas3650atlas3650 Posts: 11Questions: 0Answers: 0
    PS not sure you're aware, but this forum is running realllly slowly right now...
  • allanallan Posts: 63,578Questions: 1Answers: 10,483 Site admin
    Hi atlas3650,

    Thank you very much indeed for your kind words - they are very much appreciated!

    Regarding your two questions:

    1. Are you looking to retain sorting on some columns but not others? If you switch sorting off completely then it will not add the click handler to the TH elements. Having said that, I agree that this should really be regarded as a bug in DataTables and I've added it to my to-do list for the next release.

    And in turn, having said that... I think that bubbling is probably the issue here. If add your event handler to an element inside the TH element, then that should get the click event first, and that will then be passed on to the DataTables handler - unless to stop the bubbling. This can be done with e.stopPropagation() - if this indeed the problem you might find this article from PPK most interesting: http://www.quirksmode.org/js/events_order.html

    2. What you can do here is to use the fnFIlter() API function along with a drop down menu (assuming that is what you were going for) and the $().change( function() { ... } ) handler. For example:

    [code]
    var oTable = $('#example).dataTable();
    $('whatever').change( function () {
    oTable.fnFilter( this.value, 0 );
    } );
    [/code]

    That would take the value of the select menu and apply it to the first column. To get "All" just have a blank value.

    3. The forum speed - seem okay to me at the moment. Is it okay for you? Perhaps you caught the server at a bad moment - it's a bit temperamental :-)

    Regards,
    Allan
  • atlas3650atlas3650 Posts: 11Questions: 0Answers: 0
    edited May 2009
    Allan,

    Thanks for your pointers and snappy reply on a weekend, no less. That helped me a lot. Now I can get clicks; I was binding clicks to the wrong element, as it turned out, and stopping propogation also helped.

    I was also able to get the filtering working, using a hidden column with numeric representations of the strings described above as "A", "B", "C" because in actual fact those strings could have some overlap and filtering might not work perfectly if not numeric.

    Now, I have a several followup questions. I think your answers to these are bound to help others.

    1/ The select I set up for filtering works fine in Fox3.0.10 *and* IE7, but in Safari3, you cannot make it drop down. Other selects on the page render and work fine; only the one in the header is broken (and only if you apply dataTable() against the table, it's fine until then).

    1a/ A related safari bug is the following: when you page to the last page, a big blue box covers up the entire table. I was sure this was something wacky in my own css until I saw it happening in safari on your own example pages, e.g. on the datatables.net home page (assuming you have safari, just page through a bit and a spurious blue box will show up covering part of the table including the header and the footer, but not always on the same page). The version of safari I have is 3.2.3 (MacOS 10.5.7). I hope you have a mac to help solve this; it's critical that the plugin work in Safari for me. If you don't, perhaps I can help figure out the issue.

    2/ The second issue is with the paginator (for any browser). When you get to the last page, it moves up (because the number of rows shown is usually less than the page length). Is there a way to prevent this, so that there's blank space or blank rows for the last few non-populated rows, say? It's very inconvenient for the user for the paginator to move. I suppose there's a CSS solution somehow but it'd be nicer to do it within the params of the plugin.

    2a/ is it possible to customize the text of the info displayed? I mean "Showing 1 to 5 of 14 entries", or "filtering on...". Reason being, "entries" is not appropriate for my purpose.

    3/ For SEO reasons, ideally I could render the table out as part of the page, and then apply dataTables to it (vs creating the table dynamically using Ajax/json), which is uncrawlable. Unfortunately, this has the side effect that for a split second the un-dataTable'd table shows up. If I hide() the table until I've applied dataTable(), dataTable does not calculate column widths correctly (I know this is a jquery issue with hidden dom elements, not a dataTable issue, but it's still onerous). In a perfect world, the minute the table is visible, it's already dataTable()'d. Any suggestions on how to accomplish this cleanly? The only idea I have is to put the table off page using CSS absolute positioning, then defeat that once I've dataTable()'d, but that seems kind of hackish.

    4/ Not a bug but a warning worth putting in your docs somewhere: an extra comma in your array for aoColumns (and any other array for configuring the plugin) will break IE in a somewhat confusing way (IE can't parse this javascript but complains about it deep in your code):

    [code]
    "aoColumns" : [ { "bSortable" : true},
    { "bSortable" : true },
    { "bSortable" : true },
    { "bSortable" : true },
    { "bSortable" : false },
    { "bSortable" : false, "bVisible" : false },
    { "bSortable" : false }, // that trailing comma will make IE blow up
    ]
    [/code]

    In the above example, that trailing comma was fine for safari and fox but IE chokes on it.





    Lastly, unrelated to this, I think the reason your site is slow isn't your fault. From where I am (California), there's a bottleneck in between:

    [code]
    3 ge-2-41-ur01.pittsburg.ca.sfba.comcast.net (68.87.197.33) 14.875 ms 14.476 ms 16.188 ms
    4 68.85.154.38 (68.85.154.38) 9.714 ms 12.012 ms 9.205 ms
    5 pos-1-8-0-0-cr01.sanjose.ca.ibone.comcast.net (68.86.91.229) 16.151 ms 26.326 ms 20.103 ms
    6 pos-0-0-0-0-pe01.11greatoaks.ca.ibone.comcast.net (68.86.86.50) 21.110 ms 14.669 ms 20.544 ms
    7 xe-9-3-0-0.sjc10.ip.tiscali.net (213.200.80.165) 28.477 ms 13.728 ms 14.809 ms
    8 xe-2-1-0.lon20.ip.tiscali.net (89.149.186.89) 160.197 ms xe-1-0-0.lon20.ip.tiscali.net (89.149.186.81) 162.757 ms 157.718 ms
    9 blueconnex-gw.ip.tiscali.net (77.67.67.138) 158.966 ms 163.208 ms 161.343 ms
    10 85.234.144.244 (85.234.144.244) 160.846 ms 160.583 ms 160.299 ms
    11 orion.sprymedia.co.uk (85.234.144.226) 168.604 ms 160.261 ms 161.247 ms
    [/code]
  • allanallan Posts: 63,578Questions: 1Answers: 10,483 Site admin
    Good to here you got everything from the first post working. So now the second :-)

    1. My guess is that there is an overlapping element here - Firebug or Webkit's Inspector will be able to tell you if this is the case. If so then that element will be "eating" the event. There certainly should be no reason why DataTables would stop a select element working...

    1a. The blue box you are seeing is "text selection". I had thought I had stopped this from happening, but I'll have another look. Safari is basically seeing your two clicks on the pager as a double click and so is selecting text. A fix should be in the next release (hopefully not to far away).

    2. The best way to do this is in CSS imho. That way each developer can customise the display to suit their needs. One option is to set a min-height either on the table or a div wrapped around the table (you can add one using sDom), or you might just set a straight height on a wrapping div (which would then work in IE as well).

    2a. Customising the language - yes indeed this is possible. Have a look at the useage page: http://datatables.net/usage#language

    3. Ah yes the old with progressive enhancement... If you want your JS to execute on your HTML as quickly as possible the thing to do is place a script tag with the required JS directly after your table, or table wrapping element in the HTML. It is worth noting that some operations (not sure if the one's that DataTables uses require this) will require the full DOM to be loaded. Failing this, then your option sound like quick a good one. An alternative would be to have the data in the first page already loading into HTML and then have DataTables using Ajax to get the full source.

    This hide issue with the columns is due tot he fact that the web-browser's rendering engine doesn't actually draw elements it doesn't need to, and therefore no height/width information is available. visibility: hidden however would cause it to be rendered, but can cause a big gap in your design until it is made visible.

    4. I'm going to compile an FAQ sometime soon and this will be near the top of the list. It's not often I say this, but I think IE is actually correct in complaining about this. Having a trailing comma would suggest that there is another element to the array, and there isn't, so I think this is invalid JSON. Should the JS parser ignore it or add a NULL? It's a tricky one, so the best way is just to avoid it :-)

    Traceroute: Thanks for this. It looks like there is quite a nasty hop in the tiscali network (a bit surprised your connection goes through their system...). Unfortunately not sure how much I can do about this, but I'll get in touch with the networking guys who host this server.

    Regards,
    Allan
  • atlas3650atlas3650 Posts: 11Questions: 0Answers: 0
    hi Allan,

    Thanks again for your copious replies. The controls you've created for customizing the text messages in the info area are awesome!

    There is one bug here that I believe is on your side w/r/t Safari. After trying for the past hour to track down some unbalanced div, etc, I've eliminated everything and boiled it down to the following example which you can test in Safari:

    [code]
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">




    google.load("jquery","1.3.1");



    $(document).ready(function () {
    oTable = $('#questionsForMeTable').dataTable( {
    "bFilter" : false,
    "bLengthChange" : false,
    "iDisplayLength" : 5,
    "bPaginate" : true,
    "sPagination" : "two_button",
    "aoColumns" : [ { "bSortable" : false },
    { "bSortable" : true }
    ]
    } );
    });






    AllFriendFriend of a friend
    Category




    1
    Test1


    2
    Test2


    3
    Test3


    4
    Test4


    5
    Test5





    [/code]

    You'll see there's no styles, external code, etc, involved. The dropdown just does not drop down! The element actually gets click events fine, which you can test out, but you cannot change the value of the dropdown. In fact, if you turn sorting on on the column, it will sort *even* if you do a stopPropogation in the handler bound to a click on the dropdown (which I really don't understand). (of course a handler bound to change() won't ever run since you can't change the dropdown). Note that this ONLY happens in safari, e.g. if i add:

    [code]
    $('#connectionLevel').click( function(e) {
    e.stopPropagation();
    alert('we are here');
    return(false);
    });
    [/code]
  • atlas3650atlas3650 Posts: 11Questions: 0Answers: 0
    edited June 2009
    I have come up with a workaround that works in Safari.

    Basically, there's some event binding conflict going on. So to solve it, I set an id on the TH where I want to have my control, and unbind it completely. Then I append my control to that TH and bind it. This isn't gorgeous, but it works, in case others run into this issue. Here's code that actually does what I want correctly in Safari.

    [code]
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">




    google.load("jquery","1.3.1");



    $(document).ready(function () {
    oTable = $('#questionsForMeTable').dataTable( {
    "bFilter" : false,
    "bLengthChange" : false,
    "iDisplayLength" : 5,
    "bPaginate" : true,
    "sPagination" : "two_button",
    "aoColumns" : [ { "bSortable" : false },
    { "bSortable" : false },
    { "bSortable" : true }
    ]
    } );
    $('#friendSelector').unbind();
    $('#friendSelector').html('Show: AllFriendFriend of a friend');
    $('#connectionLevel').change( function(e) {
    oTable.fnFilter(this.value, 1);
    e.stopPropagation();
    return(false);
    });

    });






    Id

    Connection Level




    1
    1
    Friend


    2
    2
    Friend of a friend


    3
    2
    Friend of a friend


    4
    1
    Friend


    5
    3
    Member





    [/code]
  • allanallan Posts: 63,578Questions: 1Answers: 10,483 Site admin
    Hi atlas3650,

    Sorry for the delay in getting back to you about this. Two things here:

    1. The issue with the drop down menu in Safari - thanks very much for the example, that really made debugging this issue much simpler!

    The reason that this didn't work was that I had a "return false" in order to prevent text selection when the shift key is pressed and the user clicks on a column (for multi-column sorting). This was overly brutal and I've now put in a check to ensure that the shift key is depressed before stopping text selection. This does mean that the drop down menu still won't work if the shift key is pressed, but this seems like a reasonable compromise (as I would have thought that was fairly unlikely).

    2. Text selection issue in Safari (blue box) - as noted previously this was due to the browser seeing a couple of quick paging events as a double click. I've added a "prevent text selection" to the paging controls which will fix this problem.

    These two fixes will be included in the next DataTables 1.5 beta release (next day or two). Thanks very much for taking the time to report the problems you were having and investigating them thoroughly!

    Regards,
    Allan
This discussion has been closed.