0

Jquery UI datepicker seems to disregard the "readonly" attribute of input fields.

In the code below, I'm able to disable the popup calendar by using the "beforeShow" event (thanks to another answer on StackOverflow - reproduced here for others' benefit)

However, I can't prevent the Enter key from populating the textbox with the current date. I tried intercepting the "keydown" event (below) but no joy. :-(

<input type="text" class=".input-date" readonly="readonly" />

$(".input-date").datepicker({
    beforeShow: function (input, inst) {
        if ($(input).attr("readonly")) {
            inst.dpDiv = $('<div style="display: none;"></div>');
        }
    }
})
.bind("keydown", function (e) {
    if (e.keyCode == 13 && $(this).attr("readonly") == "readonly") {
        e.preventDefault();
        e.stopPropagation();
        return false;
    }

})

Also FWIW: The date field's "readonly" is turned on & off dynamically on my page, so I can't just not apply the datepicker plugin to readonly fields.

Any suggestions?

Bumpy
  • 1,290
  • 1
  • 22
  • 32

4 Answers4

2

Use prop instead of attr to check the readonly. Also, check it for truthness:

if ($(this).prop("readonly")){
    // do stuff
}

Update

Use the e.which for detecting which key was pressed.
Also, use event.stopImmediatePropagation() for stopping the default action:

if (e.which == 13 && $(this).prop("readonly")) {
    e.preventDefault();
    e.stopImmediatePropagation();
    return false;
}

Update 2

Also, you may want to bind to keydown before you activate the datepicker because of order of handle execution - event handlers are executed in the same order that they were bound - see this SO question for example.
So you should probably do:

$(".input-date").bind("keydown", function (e) {
    if (e.which == 13 && $(this).prop("readonly")) {
        e.preventDefault();
        e.stopImmediatePropagation();
        return false;
    }
}).datepicker({
    beforeShow: function (input, inst) {
        if ($(input).prop("readonly")) {
           inst.dpDiv = $('<div style="display: none;"></div>');
        }
    }
});
Community
  • 1
  • 1
Shimon Rachlenko
  • 5,469
  • 40
  • 51
  • Hi Shimon, thanks for your answer. 'prop("readonly")==true' is probably is better form than 'attr("readonly")=="readonly"', as you suggest, but that is not the problem; Even if I have no condition at all, I still can't prevent the ENTER key from populating the textbox with the default date. :-( – Bumpy Mar 06 '13 at 02:05
  • Sadly this line `inst.dpDiv = $('
    ');` completely mess datepicker and after you remove readonly attribute from field datepicker no longer works (because it's DIV is replaced with empty one). Any ideas how to get around this? `inst.dpDiv.hide()` doesn't help too.
    – DarkSide Jun 13 '14 at 11:36
  • This works as expected if we do like this in beforeShow: `if($(input).attr("readonly")){if(inst.dpDivOrig===undefined)inst.dpDivOrig=inst.dpDiv;inst.dpDiv=$("
    ");}else{if(inst.dpDivOrig!==undefined)inst.dpDiv=inst.dpDivOrig;}`
    – DarkSide Jun 13 '14 at 12:17
0

you should be using .prop()

 <input type="text" class=".input-date" readonly="readonly" />

    $(".input-date").datepicker({
        beforeShow: function (input, inst) {
            if ($(input).prop("readonly")) {
                inst.dpDiv = $('<div style="display: none;"></div>');
            }
        }
    })
    .bind("keydown", function (e) {
        if (e.keyCode == 13 && $(this).prop("readonly") == "readonly") {
            e.preventDefault();
            e.stopPropagation();
            return false;
        }
    })
DarkAjax
  • 15,955
  • 11
  • 53
  • 65
Matt Busche
  • 14,216
  • 5
  • 36
  • 61
  • Thanks Matt, but determining readonly-ness is not the problem. See my response to Shimon below who offered a similar suggestion. – Bumpy Mar 06 '13 at 02:07
0

You can save the value beforeShow in a var and set it back to the input onSelect if the input is readonly:

var onShowValue;

$(".input-date").datepicker({
    beforeShow: function (input, inst) {
        if ($(input).prop("readonly")) {
            inst.dpDiv = $('<div style="display: none;"></div>');
        }
        onShowValue = $(input).val();
    },
    onSelect: function (date) {
        if ($(this).prop("readonly")) {
            $(this).val(onShowValue);
        }
    }
});
shere
  • 101
  • 3
  • Thanks shere. This worked, but although your code was more compact, I accepted Shimon's solution only because it seemed more "correct"; actually preventing the event rather than undoing the result of the event. – Bumpy Mar 06 '13 at 21:20
0

Ok, I know this is old, but if anyone else comes along (like me) and is looking at how to do this, there's a cleaner way, per the jQuery UI docs:

$("input[readonly='']").datepicker( "option", "disabled", true );

You'd have to set the disabled property alongside whatever code is toggling the readonly attribute of your inputs. In my case, the page was loading with the readonly elements already statically set, so the selector provided simply disables anything specified as readonly.

Steven
  • 912
  • 1
  • 7
  • 13