Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uncaught TypeError: Cannot read property 'left' of undefined

Tags:

jquery-ui

I can't seem to show a datepicker from jQuery UI on a hidden field as I get this error:

Uncaught TypeError: Cannot read property 'left' of undefined

When I use a regular text field, I don't seem to have a problem. I get this error with both jQuery UI 1.9.0 and 1.9.2, the version of jQuery is 1.8.3

html

<table>
    <tr>
        <td> 
            <small class="date_target">until <span>Dec. 31, 2013</span></small>
            <input type="hidden" class="end_date" />
        </td>
    </tr>
</table>

JS

$(".end_date").datepicker({
    dateFormat: 'yyyy-mm-yy',
    yearRange: '-00:+01'
});

$('.date_target').click(function () {
    $(this).next().datepicker('show');
});

I provided a (not) working example on this jsfiddle too

like image 768
J. Ghyllebert Avatar asked Jun 14 '13 09:06

J. Ghyllebert


1 Answers

Let's check datepicker _findPos function

$.datepicker._findPos = function (obj) {
        var position,
            inst = this._getInst(obj),
            isRTL = this._get(inst, "isRTL");

        while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.visible(obj))) {
            obj = obj[isRTL ? "previousSibling" : "nextSibling"];
        }

        position = $(obj).offset();        

        /*because position of invisible element is null, js will break on next line*/
        return [position.left, position.top]; 
    };

If target obj of datepicker is invisible, it will use the closest sibling position which is not invisible

There are several solutions:

Solution 1

Because of LTR, you can exchange position of two element

<tr>
    <td> 
        <input type="hidden" class="end_date" />
        <small class="date_target">until <span>Dec. 31, 2013</span></small>
    </td>
</tr>

Solution 2

Add an visible element next to the hidden element, so datepicker will find the visible element position

<tr>
    <td>
        <small class="date_target">until <span>Dec. 31, 2013</span></small>
        <input type="hidden" class="end_date" /><span>&nbsp;</span>
    </td>
</tr>

Solution 3

Redefine _findPos function, so you can set position of calendar wherever you want

$.datepicker._findPos = function (obj) {
        var position,
            inst = this._getInst(obj),
            isRTL = this._get(inst, "isRTL");

        while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.visible(obj))) {
            obj = obj[isRTL ? "previousSibling" : "nextSibling"];
        }

        position = $(obj).offset();
        // if element type isn't hidden, use show and hide to find offset
        if (!position) { position = $(obj).show().offset(); $(obj).hide();}
        // or set position manually
        if (!position) position = {left: 999, top:999};
        return [position.left, position.top]; 
    };
like image 97
jasperjian Avatar answered Jan 03 '23 18:01

jasperjian