Calling fnFilter on blur/change events swallows tbody clicks

Calling fnFilter on blur/change events swallows tbody clicks

twadzillatwadzilla Posts: 5Questions: 0Answers: 0
edited February 2012 in Bug reports
The following code illustrates an issue when invoking fnFilter upon blur or change events. When the user focuses in the search textbox, then either clicks any of the links or inputs in the tbody, there should appear an alert stating 'clicked'. However most browsers behave as if there was no click event--it simply gets swallowed. Subsequent clicks on the same element or clicks on the links labeled "thead" or "outside" behave as expected.

Note that this behavior occurs regardless of how the click handler is attached--using bind, delegate, or the onclick/href attributes, whether on the search box provided by DataTables or externally defined text input.

This issue is reproduceable in IE 9.0.8112.16421, Chrome 18.0.1025.39 (beta), Safari 5.1.2 on Windows 7 x64. Firefox 10.0.2 does not seem to be affected by this issue.

[code]




thead


tbody

button
checkbox
radio


outside



$(document).ready(function () {
var oTable = $('table').dataTable({
'sDom': 'ft',
'bSort': false
});

$('body').delegate('.click', 'click', function () {
alert(this.id + ': clicked');
return false;
});

$('body').delegate('input[type="text"]', 'blur', function () {
oTable.fnFilter('');
});
});



[/code]

Replies

  • twadzillatwadzilla Posts: 5Questions: 0Answers: 0
    I was able to reduce the repro code to the following:

    [code]


    then click here

    [/code]

    In Firefox the above code produces the 'clicked' dialog every time, while in other browsers, the initial click event gets swallowed. Apparently browsers react differently when an element that has a pending event is moved around in the DOM.

    Attaching a click handler to rows is a common scenario (see http://www.datatables.net/release-datatables/examples/api/row_details.html) and adding a call to fnFilter on the blur/change event reliably handles the case where the user invokes cut/paste using the mouse or menu.

    However since DataTables uses the appendChild/removeChild methods on the table rows in _fnDraw (lines 1414-1437), adding a call to fnFilter upon blur/change combined with a click handler on the table rows seems to trigger this issue.

    As a workaround one can bind to the 'cut' and 'paste' events and utilize setTimeout to access the current input value, e.g.

    [code]
    function applyFilter() {
    oTable.fnFilter($('input[type="text"]').val());
    }
    $('input[type="text"]').bind('keyup cut paste', function (ev) {
    if (ev.type == 'keyup') {
    applyFilter();
    } else {
    setTimeout(applyFilter,0);
    }
    });
    [/code]

    Perhaps in the future the 'input' event (http://www.w3.org/TR/DOM-Level-3-Events/#event-type-textinput) should solve this case, but at present compatibility is limited to WebKit: http://quirksmode.org/dom/events/keys.html#t010
  • allanallan Posts: 63,214Questions: 1Answers: 10,415 Site admin
    It sounds like the issue noted here: http://datatables.net/faqs#events .

    Allan
  • twadzillatwadzilla Posts: 5Questions: 0Answers: 0
    Allan--thank you for this terrific plugin and for your consideration. Unfortunately using live() or delegate() does not overcome this issue, as the initial post states.

    Also, is there a reason why the filter input provided by DataTables doesn't listen by default for cut/paste events invoked by a mouse or menu command?
  • allanallan Posts: 63,214Questions: 1Answers: 10,415 Site admin
    > Also, is there a reason why the filter input provided by DataTables doesn't listen by default for cut/paste events invoked by a mouse or menu command?

    It uses a 'keyup' event to watch for text changes - hence a paste by a mouse will be missed. I'm not 100% sure how to capture that to be honest. Possibly mouse up. I'll experiment a bit.

    Regarding the events issue - might you be able to put a working example together using the live site: http://live.datatables.net ?

    Thanks,
    Allan
  • twadzillatwadzilla Posts: 5Questions: 0Answers: 0
    Sure, here is a trivial example that illustrates the events issue:
    http://live.datatables.net/ixadeg/4/

    This attaches a 'click' handler on table cells and a 'change' handler on the filter input that invokes fnFilter to address precisely the case where the filter has been updated by cut/paste operations from mouse or menu actions, as opposed to keypresses. As you can see, once the filter is changed (by keypress or otherwise) and a table cell is directly clicked, the click handler is not fired in most browsers (Firefox and possibly Opera being the only exceptions).

    Generally speaking, the 'cut' and 'paste' events are not reliable for determining the current filter value since they are triggered before the input element's value is updated. The workaround suggested above involving setTimeout seems to reliably handle this case in all browsers.
  • allanallan Posts: 63,214Questions: 1Answers: 10,415 Site admin
    Thanks for the example, but I'm afraid I really don't understand why it doesn't work! If you blur the focus of the text box by clicking anywhere else on the page before then clicking the table it works just fine, so it is something related to the focus of the text box, but I think we would need someone who is a lot more expert in how jQuery handles events than me in order to get to the bottom of this one.

    Allan
  • twadzillatwadzilla Posts: 5Questions: 0Answers: 0
    The "reduced" repro code above (http://live.datatables.net/uwoken) serves to illustrate that the problem lies not with jQuery but in the way that browsers react when an element that has a pending event is moved around in the DOM. Most browsers seem to simply discard the pending event, but somehow Firefox is able to follow through.
  • satishlksatishlk Posts: 5Questions: 0Answers: 0
    I need dynamic row numbers in datatables.i am unable to get dynamic row numbers but getting static row numbers .please kindly help in this regard
This discussion has been closed.