views:

2362

answers:

8

I'm working with a dynamic DOM here, and have called the jQuery UI datepicker to all inputs with a specific class name, in this case .date

It works great with the first, static, construct but when I clone it the event handlers don't seem to want to move over. I get the Firebug error:

inst is undefined

I tried looking into jQuery's new live() function but couldn't combine the two. Any ideas?

+6  A: 

Ah, got it. Right after I append the HTML to the DOM I run this on all the inputs I'd like to have a datepicker pop up with. Datepicker adds a class to elements it has been attached to, so we can filter out existing inputs and only apply it to new ones.

$('.date').not('.hasDatePicker').datepicker();

I hope this helps people as I was Googling for days and didn't find anything!

You should also note that it would be faster to check for input.date in the new generated HTML by setting that as a context, rather than the whole page, as it will save time.

Will Morgan
Will, Thanks a lot! You saved a couple hours of my life :)
Fedyashev Nikita
When using a dynamic DOM this solution didnt help me when I was (jquery) cloning table rows with events. My solution was to do $('.date').removeClass('hasDatepicker').datepicker();
David Liddle
David, what jQuery core and UI version are you using? This was for 1.3.2 and 1.7 respectively, and the solution has worked with other implementations. Whatever floats your boat though!
Will Morgan
+1  A: 

I had a similar Issue, I had multiple tables on a page and each had multiple datepickers, also on click of button "AddLine" it added a table row with dynamic HTML and datepicker.

I realized after a lot of search that my input date fields had no "id" defined they looked like this

<input type="text" class="datepicker" name="mDate1" value="" size=8 >

jquery was pointing all the date fields values to the very first date field defined on page, the calendar would popup on all the date fields but the value of 1st date field would change, I made a change to the html like this

<input type="text" class="datepicker" id="Date1" name="mDate1" value="" size=8 >

by adding a "id" and it started working, for the dynamic date fields I change the Id like this

var allColumns = $("#"+$tableId+" tr:last td"); 
  $(allColumns).each(function (i,val) {
   if($(val).find(":input").hasClass("datepicker")){
     $(val).find(":input").attr("id",newId+$(val).find(":input").attr("id"));
   }
     });
Richipal
+2  A: 

Use jQuery selectors:

$(".mydatepicker:not(.hasDatepicker)").datepicker()
Quaternion
A: 

I experienced the same symptom, in this caused by having a td containing element with the same id attribute as the input,

 <td id="fld_xyz"><input id="fld_xyz" class="date" /></td>

I know this isn't ideal anyway, but it's worth knowing that the datepicker component seems to be relying on the uniqueness of the id.

Stephen Francis
Post necro, but I hope you're not using duplicate IDs any more these days...
Will Morgan
+1  A: 

I had this problem. My situation ended up being I had another element with the same ID as the input with the datepicker.

Scott K
I had the same issue - the div enclosing the input text field had the same ID as the text field. Removing the id on the div fixed the issue.
Killian
A: 

i have the same problme here but it doesn't work with any of the solutions above and i don't kow why. This is my code:

HTML

<table class="preturi" border="0" cellspacing="1" cellpadding="5" id="pricesHolder">
    <tbody>
    <tr>
    <th colspan="2">Perioada</th><th colspan="4">Preturi de persoana pe tip de camera</th><th width="60">Actiuni</th>
    </tr>
    <tr>
        <td align="left" valign="top"><strong>De la</strong></td>
        <td align="left" valign="top"><strong>Pana la</strong></td>
        <td align="left" valign="top"><strong>Single</strong></td>
        <td align="left" valign="top"><strong>Double</strong></td>
        <td align="left" valign="top"><strong>Triple</strong></td>
        <td align="left" valign="top"><strong>Discount</strong></td>
    </tr>
    <tr id="myrow" class="hideElement">
        <td><input type="text" name="dela" id="dela" size="8" class="perioada" /></td>
        <td><input type="text" name="panala" id="panala" size="8" class="perioada" /></td>
        <td><input type="text" name="single" id="single" size="8" /></td>
        <td><input type="text" name="double" id="double" size="8" /></td>
        <td><input type="text" name="triple" id="triple" size="8" /></td>
        <td><input type="text" name="discount" id="discount" size="8" />&nbsp;%</td>
    </tr>
    <tr>
        <td><input type="text" name="prices[1][dela]" id="dela1" size="8" class="perioada" /></td>
        <td><input type="text" name="prices[1][panala]" id="panala1" size="8" class="perioada" /></td>
        <td><input type="text" name="prices[1][single]" id="single1" size="8" /></td>
        <td><input type="text" name="prices[1][double]" id="double1" size="8" /></td>
        <td><input type="text" name="prices[1][triple]" id="triple1" size="8" /></td>
        <td><input type="text" name="prices[1][discount]" id="discount1" size="8" />&nbsp;%</td>
        <td><input type="button" value="Adauga" id="addPrice" /></td>
    </tr>
    </tbody>
    </table>

JAVSCRIPT CODE

$(document).ready(function() {
    var currentPrice = 1;

    $("#addPrice").click(function() {
        currentPrice++;
        $newPrice = $("#myrow").clone(true);

        $newPrice.children("td").children("input").each(function(i) {
            var $currentElem= $(this);
            $currentElem.attr("name","prices["+currentPrice+"]["+$currentElem.attr("name")+"]");
            $currentElem.attr("id",$currentElem.attr("id")+currentPrice);
        });

        $newPrice.appendTo("#pricesHolder");
        $newPrice.removeClass("hideElement");
        $newPrice.attr("id","myrow"+currentPrice);

        $newPrice.append($([
            '<td>',
            '<input type="button" value="Sterge" onclick="$(this).parents(\'#myrow'+currentPrice+'\').remove();return false;">',
            '</td>'].join(''))
        );
    })

$('.perioada').datepicker('destroy').datepicker({ 
        dateFormat: 'yy-mm-dd',
        firstDay: 1,
        minDate: 'D'
});
});

Any ideas? pls?

gaby
Typo. prioada -> perioada.
Will Morgan
Use comments for comments, stop posting answers.
Will Morgan
help ... anyone ... :D i have no more ideas
gaby
A: 

Use $j(id or class).removeClass('hasDatepicker').datepicker();

It is working

kishore
You're not destroying the datepicker, though, which means you're essentially rebinding something each time that code is triggered. So instead of one datepicker, you'll have two (or it'll happen twice - not tested).So yeah, it might look like it works, but it won't function optimally.
Will Morgan
It's not happening twice . It is working perfectly fine
kishore
Unfortunately, what you're doing in addition to setting datepickers on new elements, is rebinding everything to previously created elements which is going to take up memory. This might not be noticeable over short periods of time, but if the page never reloaded and you did this many times, you would notice a difference. It's generally considered good programming practice to look after memory :)
Will Morgan
A: 

You need to use the 'live' event to make it work with dynamic DOM. So, if the class for your datepicker inputs is 'date-input', following code will make it work:

$(document).ready(function() {
    $('.date-input').live('click', function() {
    $(this).datepicker('destroy').datepicker({showOn:'focus'}).focus();
        });
});
Tommy
No. You're recreating a datepicker every time the input is clicked, which is not performant.
Will Morgan

related questions