Closed myaptad closed 1 year ago
I think you were on the right track by triggering change
on the hidden element. I got it to work with:
$(document).on("daPageLoad", function () {
$('input[type="date"]').each(function () {
var dateElement = this;
$(dateElement).attr("type", "hidden");
var parentElement = $('<div class="row px-1">');
var monthParent = $('<div class="col-sm-5 px-0">');
var dayParent = $('<div class="col-sm-4 px-0">');
var yearParent = $('<div class="col-sm-3 px-0">');
var monthElement = $('<select class="form-select">');
var dayElement = $('<select class="form-select">');
var yearElement = $('<select class="form-select">');
var today = new Date();
var dateEntered;
if ($(dateElement).val()) {
var utcDate = new Date($(dateElement).val());
dateEntered = new Date(
utcDate.getUTCFullYear(),
utcDate.getUTCMonth(),
utcDate.getUTCDate()
);
} else {
dateEntered = null;
}
var opt = $("<option>");
opt.val("");
opt.text("Month");
monthElement.append(opt);
for (var month = 0; month < 12; month++) {
opt = $("<option>");
if (month < 9) {
opt.val("0" + (month + 1));
} else {
opt.val(month + 1);
}
var dt = new Date(1970, month, 15);
opt.text(dt.toLocaleString("default", { month: "long" }));
if (dateEntered && month == dateEntered.getMonth()) {
opt.attr("selected", "selected");
}
monthElement.append(opt);
}
opt = $("<option>");
opt.val("");
opt.text("Day");
dayElement.append(opt);
for (var day = 1; day <= 31; day++) {
var opt = $("<option>");
if (day < 10) {
opt.val("0" + day);
} else {
opt.val(day);
}
opt.text(day);
if (dateEntered && day == dateEntered.getDate()) {
opt.attr("selected", "selected");
}
dayElement.append(opt);
}
opt = $("<option>");
opt.val("");
opt.text("Year");
yearElement.append(opt);
for (
var year = today.getFullYear();
year > today.getFullYear() - 50;
year--
) {
opt = $("<option>");
opt.val(year);
opt.text(year);
if (dateEntered && year == dateEntered.getFullYear()) {
opt.attr("selected", "selected");
}
yearElement.append(opt);
}
function updateDate() {
if (
$(yearElement).val() != "" &&
$(monthElement).val() != "" &&
$(dayElement).val() != ""
) {
$(dateElement).val(
$(yearElement).val() +
"-" +
$(monthElement).val() +
"-" +
$(dayElement).val()
);
$(dateElement).trigger("change");
}
}
$(dateElement).before(parentElement);
$(monthParent).append(monthElement);
$(parentElement).append(monthParent);
$(dayParent).append(dayElement);
$(parentElement).append(dayParent);
$(yearParent).append(yearElement);
$(parentElement).append(yearParent);
yearElement.on("change", updateDate);
monthElement.on("change", updateDate);
dayElement.on("change", updateDate);
updateDate();
});
});
and
features:
javascript: datereplace.js
---
question: |
When were you born?
fields:
- Date of birth: date_of_birth
datatype: date
- "Do you remember the dinosaurs?": remembers_dinosaurs
datatype: yesnoradio
js show if: |
val('date_of_birth') && Date.parse(val('date_of_birth')) < Date.parse('1980-01-01')
---
mandatory: True
question: |
You were born on ${ date_of_birth }.
The Bootstrap classes in the JavaScript file were out of date so I changed them.
Hello, Thanks alot for looking into this. I confirm this issue to have been fixed. I am marking this ticket to closed. Much appreciated. Thanks!
Hello,
These are related to the date control so re-opening the ticket instead of new issue.
Thanks
The min
and max
validators work for me when I add them to the recipe.
question: |
When were you born?
fields:
- Date of birth: date_of_birth
datatype: date
min: 1970-01-01
max: 2020-01-01
The validators work via the jQuery Validation plugin, so the max
and min
values aren't in the <input>
element itself. They are in daValidator.settings.rules
.
You could write JavaScript that detects if the device is Android and then converts the field to text:
$(document).on("daPageLoad", function () {
var isAndroid = // your code here;
if (isAndroid){
$('input[type="date"]').each(function () {
$(this).attr('type', 'text');
});
}
});
so that the browser treats the field as plain text.
Thank you for reverting back on this. I should have been bit more clear earlier. Let's see if I can clarify further:
I am not seeing what you are seeing. When I use my datereplace.js
, the standard docassemble input validation functionality based on the jQuery Validation plugin works as normal, and I get the warning messages if the date is outside the min or max. Also when I use JavaScript to change the type
of the input element to text
, the jQuery Validation plugin makes sure that I enter a valid date.
Hello there, I can confirm that setting the field to text in javascript does work along with its proper validation.
However, after playing around a bit, it seems like there is a usage specific behavior or possibly a bug in the code. We can see the behavior using code below which has minor changes to your example. The validation stops working when the last field is commented/removed as shown. Do you see some issue with usage as such?
features:
javascript: datereplace.js
---
question: |
When were you born?
fields:
- Date of birth: date_of_birth
datatype: date
max: ${ today() }
# - "Do you remember the dinosaurs?": remembers_dinosaurs
# datatype: yesnoradio
# js show if: |
# val('date_of_birth') && Date.parse(val('date_of_birth')) < Date.parse('1980-01-01')
---
mandatory: True
question: |
You were born on ${ date_of_birth }.
In 1.4.27 I changed the jQuery Validation Plugin settings so that this will work more consistently.
Works now, thank you!
Problem: Date dependent controls show and hide perfectly with DA's built-in date picker using "js show if" but stop to show/hide with datereplace.js included in the interview. Question: Is there anything specific that needs to be taken into account while using "js show if" with variable set by custom date picker like as demonstrated here https://docassemble.org/docs/recipes.html#customdate . I see note that datereplace.js adds nameless elements to DOM but for "js show if" DA matches element name mentioned in javascript expression. I also tried to trigger onchange on the hidden element but that does not seem to help. Thanks