March 14, 2012

Adding datepicker event handler multiple times

Question by esviko

Using jQuery I’m trying to add the datepicker event handler to an input element.

    <div id="Box_tmpl" style="border:solid 1px #777; background:#ddd; display: none;">
        <a class="remove-box" href="#">remove</a>
        <div>
            <label for="PeriodStart">Period (start):</label>
            <input id="PeriodStart" class="start-end-date" name="period_start" readonly="readonly" />
        </div>
        <div>
            <label for="PeriodEnd">Period (end):</label>
            <input id="PeriodEnd" class="start-end-date" name="period_end" readonly="readonly" />
        </div>
    </div>

    <a class="add-box" href="#" style="margin: 6px 0 10px auto;">add</a>

    <div id="Boxes">
        <div style="border:solid 1px #777; background:#ddd;">
            <a class="remove-box" href="#">remove</a>
            <div>
                <label for="PeriodStart">Period (start):</label>
                <input id="PeriodStart" class="start-end-date" name="period_start" readonly="readonly" />
            </div>
            <div>
                <label for="PeriodEnd">Period (end):</label>
                <input id="PeriodEnd" class="start-end-date" name="period_end" readonly="readonly" />
            </div>
        </div>
    </div>

    <script type="text/javascript">
        $(function(){
            $('.start-end-date').datepicker({ dateFormat: "yy-mm-dd" });

            $('.remove-box').click(function(){
                $(this).parent().remove();
            });

            $('.add-box').click(function(){
                $('#Box_tmpl').clone().removeAttr('id').show().appendTo('#Boxes');
                $('.start-end-date').datepicker({ dateFormat: "yy-mm-dd" });
                $('.remove-box').click(function(){
                    $(this).parent().remove();
                });
                return false;
            });
        });
    </script>

Adding a new box works.
Adding the remove-box event handler within the new box works.
Adding the datepicker event handler withing the new box DOES NOT work. I don’t understand why…
Creating a new element using $().clone() does the new element inherit the old element’s event handlers? If it does, may be my problem is adding the datepicker event handler multiple times to the same element… I’m running out of ideas

Answer by StilgarBF

you have to use

$().clone(true)

http://api.jquery.com/clone/

withDataAndEventsA Boolean indicating whether event handlers should be copied along with the elements. As of jQuery 1.4, element data will be copied as well.

for your question in the comment: when initializing, the datepicker adds a class “hasDatepicker” to the input. you can not reinitialize an Input with that class,
So if you want NOT to clone the events, you have to .removeClass('hasDatepicker') from your cloned input, then initialize it.

the code in your fiddle has to be changed:

$('#Box_tmpl').clone().removeAttr('id').find('input.start-end-date').removeClass('hasDatepicker').end().show().appendTo('#Boxes');
$('.start-end-date').datepicker({ dateFormat: "yy-mm-dd" });

note: .end() rewinds to the state it was until find()

Answer by Starx

In order to bind the event to the dynamically created or cloned elements use .on()

$('#Boxes').on('click', '.remove-box', function(){
   $(this).parent().remove();
});

Demo

...

Please fill the form - I will response as fast as I can!