Error binding click event in jQuery datepicker

I am trying to bind a click event with the name .ui-state-default after the jQuery dumper is displayed (I have no control over the html that the datepicker creates, so I cannot use any type of datepicker event) and it works fine using $ .bind (), but not with $ .on ().

$. bind (), which works in the console:

$('[data-handler=selectDay] a.ui-state-default').bind('click', function(){
        if($(this).hasClass('ui-state-active')) return;
        alert('changed date');
        $("button.checkout").addClass('disabled');
        $("button.checkout span").html('Choose Your Payment Method');
        $(".stage3").html(tmpl('stage3_tpl')).removeClass('noBg');
});

      

$. on () which doesn't work on the page:

$(document.body).on('click', '[data-handler=selectDay] a.ui-state-default', function(){
        if($(this).hasClass('ui-state-active')) return;
        alert('changed date');
        $("button.checkout").addClass('disabled');
        $("button.checkout span").html('Choose Your Payment Method');
        $(".stage3").html(tmpl('stage3_tpl')).removeClass('noBg');
});

      

Datepicker is not always on the page, so I don't believe I can use $ .bind ()?

Where am I going wrong?

+3


source to share


5 answers


This is due to changes DOM

. The method jQuery.on()

is linked to existing items DOM

, so it does not work for dynamically added date pickers.

JQuery Documentation: Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the .on () call

jQuery.bind()

work for existing elements as well. So it will work for the first one attached to DOM

, but not the rest of the dynamically attached ones.

The solution for this is using MutationObserver , which listen for changes DOM

and allow you to react accordingly. There is a nice plugin jQuery

called Live Query 'that makes it easy to create Mutation Observers for specific elements in your DOM

.

For example, your using code jQuery.livequery()

would look like this:

$('body').livequery(
    'table td[data-handler=selectDay] a.ui-state-default',
    function(elem){
        if( jQuery(elem).hasClass('ui-state-active') ) return;
        jQuery(elem).on('click', function(){
            $("button.checkout").attr('disabled','disabled').addClass('disabled');
            $("button.checkout span").html('Choose Your Payment Method');
        });
    }
);

      



It will listen for changes DOM

in <body> <table> <td data-handler="selectDay"] <a class="ui-state-default">

, then act accordingly when the item is clicked.

Here's a working example: http://jsfiddle.net/laelitenetwork/ej96f7m5/

/**
 * Livequery listen for DOM mutation events
 * this allows to keep listening date picker
 * events, even after being dynamically appended to
 * DOM
 */
$('body').livequery(
    'table td[data-handler=selectDay] a.ui-state-default',
    function(elem){
        if( jQuery(elem).hasClass('ui-state-active') ) return;
        jQuery(elem).on('click', function(){
            $("button.checkout").attr('disabled','disabled').addClass('disabled');
            $("button.checkout span").html('Choose Your Payment Method');
        });
    }
);
$('.clean').on('click', function(){
    /** 
     * Reset testing playground
     * This simulates dynamic DOM Mutation
     */
    jQuery('.wrap').empty();
    jQuery('.wrap').append('<input type="text" class="date-picker"/>');
    jQuery('button.checkout').attr('disabled',false);
    jQuery('button.checkout span').html('Checkout');
    $(function() {
        $( ".date-picker" ).datepicker();
    });
});
// Run datepicker
$(function() {    
    $( ".date-picker" ).datepicker();
});
      

.wrap {
    border: 1px solid #fefefe;
    background: #fafafa;
    text-align: center;
}
.wrap input {
    border: 1px solid #fcfcfc;
    padding: .5em;
    font-size: 1.1em;
    text-align: center;
    background: #f1f1f1;
}
.buttons {
    text-align: center;
    background: #fbfbfb;
}
.checkout {
    background: #ee5555;
    color: #fff;
    border: 0;
}
button:disabled {
    background: #efefef;
    color: #999;
    border: 1px solid #ccc;
}
}
      

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://staticelite.info/elitenetwork/scripts/jquery.livequery.min.js"></script>
<link href="http://code.jquery.com/ui/1.11.1/themes/black-tie/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/ui/1.11.1/jquery-ui.js"></script>
<div class="wrap">
    <input type="text" class="date-picker"/>
</div>
<div class="buttons">
    <button class="clean">Clean</button> | 
    <button class="checkout"><span>Checkout</span></button>
</div>
      

Run codeHide result


PS: Clicking the Clear button will simulate an element dynamically linked to the DOM.

+3


source


Easy!

Datepicker (jQuery-UI):

  • When you select a date (the click event added to td

    that contains a.ui-state-default

    fires a method called _selectDay

    .
  • Datepicker plugin adds methods for using the attach method called _attachHandlers

    , which attaches _selctDay

    to the elements, which have the attribute data-handler=selectDay

    , and then adds it return false

    to avoid a default and the spread (the same as event.preventDefault()

    and event.stopPropagation();

    ).

So the problem is what is return false

added to the _attachHandlers

plugin method . I deleted it and kept git for it for you (all jQuery-UI with everyone), but you can also delete it yourself by searching for the method and deleting return false

after nesting selectDay

.



Demo (External Resources - includes jQuery UI): jsFiddle

GitHub - custom jQuery-UI without returning false: GitHub p>

Checked code:

$(document.body).on('click', '[data-handler=selectDay] a.ui-state-default', function(){
    //This will be triggered after the handler of the jQuery UI: 
    if($(this).hasClass('ui-state-active')) return false;
    alert('changed date');
    /* Rest of your code */
    return false;
});

$(function() {    
    $( ".date-picker" ).datepicker();
});

      

+3


source


Use " change event binding " instead of " bind click Event "

Example:

    $('[data-handler=selectDay] a.ui-state-default').datepicker({
        dateFormat: "mm/dd/yy", 
        changeMonth: true, 
        changeYear: true, 
        yearRange: '-50:c', 
        maxDate: new Date,          
        showOn: "both", 
        buttonImage: "../../calender-icon.png", 
        buttonImageOnly: true, 
        beforeShow:   
        BeforeShowForDatePicker, 
        onClose: onCloseForDatePicker }).bind("change", function () {});

      

This will work for you.

+2


source


Better to use inline events. For example:

    $("#datepicker").datepicker({
        onSelect: function(dateText, inst) {
            alert('changed date');
            $("button.checkout").addClass('disabled');
            $("button.checkout span").html('Choose Your Payment Method');
            $(".stage3").html(tmpl('stage3_tpl')).removeClass('noBg');
        }
    });

      

See the documentation for more information.

It's worth noting that things that I would consider events like onSelect and onClose are listed in the options list and NOT in the event list.

+1


source


You need to check first if the page is ready:

$( document ).ready(function() {

});

      

If I'm right. This solved the problem one last time for me. Not sure if you are doing this?

0


source







All Articles