How do I input date in forms with xhtml or html4? - html

well I know it's easier on html5, but I have to use html4 or xhtml and I can't find any info without html5 somehow. Can anyone help and explain me how I can input a date?
<input type="text" name ="sometext">
The normal html4 or xhtml doesn't seem to have the type date as the type of input.
Thanks in advance.

This question has been asked & answered on some other StackOverflow threads, but as I'm hitting the same problem, here's more info.
Using the jQuery DatePicker is a good start, but it does not enforce format or min/max value integrity outside of the actual calendar popup. Meaning, you can type or paste some bad stuff.
Here's 2 links to sites that demo how to do it the "old way" in JS with a function:
http://www.javascriptkit.com/script/script2/validatedate.shtml
http://www.w3resource.com/javascript/form/javascript-date-validation.php
And here's a StackOverflow link to another pretty nice way to do it:
Detecting an "invalid date" Date instance in JavaScript
Personally, I need validation and restriction to min and max date ranges (SQL hates dates before 1/1/1773 and somebody tried that in my app). I'm going to wire up a function that tells me if a date string is valid, and then wire that up to the input's onchange event.
Here's the HTML for mine:
I'm also using ASP.NET and jQuery's DatePicker, so the key element for folks is the onblur event.
Here's the JS for the FixValidDate() function:
var availableDateFormats = ["mmddyyyy","mm/dd/yyyy","mm-dd-yyyy","yyyy/mm/dd","yyyy-mm-dd"];
function FixValidDate(txtDate,nulls, minDate, maxDate) {
//debugger;
formats =
{
'mmddyyyy':{
're':/^(\d{1,2})(\d{1,2})(\d{4})$/,
'month': 1,'day': 2, year: 3
},
'mm/dd/yyyy':{
're':/^(\d{1,2})[/](\d{1,2})[/](\d{4})$/,
'month': 1,'day': 2, year: 3
},
'mm-dd-yyyy':{
're':/^(\d{1,2})[-](\d{1,2})[-](\d{4})$/,
'month': 1,'day': 2, year: 3
},
'yyyy/mm/dd':{
're':/^(\d{4})[/](\d{1,2})[/](\d{1,2})$/,
'month': 2,'day': 3, year: 1
},
'yyyy-mm-dd':{
're':/^(\d{4})[-](\d{1,2})[-](\d{1,2})$/,
'month': 2,'day': 3, year: 1
}
}
dateText = txtDate.value;
matched = false;
for(i=0; i<availableDateFormats.length; i++)
{
f = formats[availableDateFormats[i]];
match = dateText.match(f.re);
if(match)
{
matched = true;
month = match[f.month];
day = match[f.day];
year = match[f.year];
//TODO validate if the numbers make sense
txtDate.value = month+"/"+day+"/"+year;
}
}
if (!matched && nulls) {
txtDate.value = "";
return false;
} else {
var timestamp = Date.parse(txtDate.value);
if (isNaN(timestamp) == false) {
var d = new Date(timestamp);
if (minDate != null) {
if (d < minDate) {
txtDate.value = "";
return false;
}
}
if (maxDate != null) {
if (d > maxDate) {
txtDate.value = "";
return false;
}
}
} else {
txtDate.value = "";
return false;
}
}
return true;
}
This is from an old library I've used for JS stuff for about a decade. You could easily find another JS validation function and swap mine out.
In my function, I required to accept a variety of date formats, and if it's a bad format, I blank out the field and keep the user in the same box. You could change that up.

HTML4 doesn't have any tags to input date by default.All you need to do is include third party library like JQUERY.
Checkout this example http://jqueryui.com/datepicker/

The basic input element is all that HTML (other than HTML5) has. You should have a label, with associated markup, for all text input. Normally you should also include information about the expected input format, as this varies by language and culture, e.g.
<label for="birth">Date of birth (day/month year):</label>
<input id="birth" type="text" name="birth" size="10">
You should also pre-check the user input client-side, with JavaScript, to give the user fast response in case of data error. Naturally, the checks should be duplicated server-side.

Related

Check date is correct + regex Angular4

I have a form in Angular4, with 2 dates: started, finished.
I want to check that the format date is dd/mm/yyyy.
I wrote:
<input pattern="((0)*[1-9]|[1-2][0-9]|(3)[0-1])(\/)(((0)*[1-9])|((1)[0-2]))(\/)\d{4}$" [(ngModel)]="filterDateStart" class="form-control" type="date" id="filterDateStart" name="filterDateStart" clrDate>
<input pattern="((0)*[1-9]|[1-2][0-9]|(3)[0-1])(\/)(((0)*[1-9])|((1)[0-2]))(\/)\d{4}$" [(ngModel)]="filterDateEnd" class="form-control" type="date" id="filterDateEnd" name="filterDateEnd" clrDate>
Then when I write invalid dates , my html doesn't say anything... I can send this form.
Then I need to check these dates.
1º Date start < date end
2º Ranges valid -> (30/20/2018) or (32/12/2018)
I see the library moment.js, but my boss says that I don't should be it. thanks, sorry for my english.
Don't use regexes, rely on the Date API :
const valid = '12/12/2018';
const invalid1 = '12/12';
const invalid2 = '12.12.2018';
const invalid3 = 'foo';
function parseDate(date) {
try {
// Make your business logic here. Examples : all must be defined and numbers, and separated with a /
const [d, m, y] = date.split('/');
if (!d || !m || !y) throw new Error();
if(isNaN(d) || isNaN(m) || isNaN(y)) throw new Error();
return new Date(y, m, d);
} catch(err) {
return 'Invalid date';
}
}
console.log(parseDate(valid));
console.log(parseDate(invalid1));
console.log(parseDate(invalid2));
console.log(parseDate(invalid3));
With that you can create a custom validator, that will be a lot more explicit than using a pattern.

How to filter or custom filter array of objects based on matching values from another object

I implemented an advance search with 15 input fields in AngularJS.
In the page load itself the result set is return from database in JSON format and i need to do the filter in client side only.
The input criteria's equivalent column is available in the result set and i need to check in its respective column only.
I am converting each column by JSON.stringify() and check with the search params like the below :
$scope.filteredData = $scope.actualData.filter(function(item) {
return JSON.stringify(item.FirstName).toLowerCase().indexOf(lowerFirstName) != -1 &&
JSON.stringify(item.LastName).toLowerCase().indexOf(lowerLastName) != -1 &&
JSON.stringify(item.EmailAddress).toLowerCase().indexOf(lowerEmailAddress) != -1 &&
JSON.stringify(item.Address1).toLowerCase().indexOf(lowerAddress1) != -1 &&
JSON.stringify(item.Address2).toLowerCase().indexOf(lowerAddress2) != -1;
...... etc // upto 15 fields
});
Since i have the 15 input fields and the actual result set contains a minimum of 50,000 records.
So converting each record's each column by JSON.stringify() and check with search params will surely cause the performance issue.
Is there any other way to achieve the filtering in client side with other approach.
I posted a sample code in Plunker with 5 input fields only : http://plnkr.co/edit/nUWZEbGvz7HG6gb91YZP
sylwester's answer is the normal way you'd filter things. Your code looks like you want to filter down to only the object that matches every input field. You code attempts to find an object where every property matches the searchParams object. At that point, I don't see what benefit there is to finding that object, because the user already created the object again! Nonetheless, here's a proper version of your code:
Live demo here.
<div ng-repeat="data in actualData | filter:searchData()">
$scope.searchData = function() {
return function(item) {
return Object.keys(item).every(function(key) {
// skip the $$hashKey property Angular adds to objects
if (key === '$$hashKey') { return true; }
var searchKey = key.charAt(0).toLowerCase()+key.slice(1);
return item[key].toLowerCase() === $scope.searchParams[searchKey].toLowerCase();
});
};
};
You really need to limit the data coming from the server for the browser's sake and for the server's sake. It's easy to implement a LIMIT, OFFSET system. It sounds like, overall, you just need to be able to query the server for a certain record.
From your comments, it seems you definitely want Angular's built in filter filter:searchParams, and just capitalize your searchParams models to match your data. For fun, I'll include more options for finer tuning.
This one almost mimics filter:searchParams. You can change > 1 to adjust when the partial matching kicks in, or have it return true only when both items are strictly equal === to disable partial matching. The difference here is that all items are hidden until matched, whereas filter:searchParams will show all items and then remove what doesn't match.
Live demo here.
$scope.searchData = function() {
return function(item) {
return Object.keys(item).some(function(key) {
if (key === '$$hashKey') { return false; }
var searchKey = key.charAt(0).toLowerCase()+key.slice(1);
var currentVal = $scope.searchParams[searchKey].toLowerCase();
var match = item[key].toLowerCase().match(currentVal);
return currentVal.length > 1 && match;
});
};
};
Lastly, to perfectly mimic filter:searchParams, you'd just put in a check to NOT filter the items until there is user input and the input is long enough to start the partial match.
Live demo here.
$scope.searchData = function() {
var partialMatchLength = 2;
return function(item) {
var shouldFilter = Object.keys($scope.searchParams).some(function(key) {
return $scope.searchParams[key] && $scope.searchParams[key].length >= partialMatchLength;
});
if (!shouldFilter) { return true; }
return Object.keys(item).some(function(key) {
if (key === '$$hashKey') { return false; }
var searchKey = key.charAt(0).toLowerCase()+key.slice(1);
var currentVal = $scope.searchParams[searchKey].toLowerCase();
var match = item[key].toLowerCase().match(currentVal);
return currentVal.length >= partialMatchLength && match;
});
};
};
First of all you ng-repeter with 50.000 records more likely is going to kill your browser, so you should thing about pagination.
Secondly you can easy filter your data using angular filter please see that demo
http://plnkr.co/edit/R8b8G4xCMSQmX1144UJG?p=preview
<div ng-controller="ListCtrl">
<br />
First Name:
<input type="text" id="txtFirstname" ng-model="searchParams.FirstName">
<br/>Last Name:
<input type="text" id="txtLastname" ng-model="searchParams.LastName">
<br/>Email Address:
<input type="text" id="txtEmailAddress" ng-model="searchParams.EmailAddress">
<br/>Address 1:
<input type="text" id="txtAddress1" ng-model="searchParams.Address1">
<br/>Address 2:
<input type="text" id="txtAddress2" ng-model="searchParams.Address2">
<br/>
<button class="btn btn-primary" ng-click="searchData()">Search</button>
<br />
<hr />
<b>Filtered Data(s):</b>
<div ng-repeat="data in actualData | filter:searchParams ">
<span ng-bind="data.FirstName"></span>
<span ng-bind="data.LastName"></span> |
Address : {{data.Address1}}
</div>
<hr />
</div>

HTML5 Time Element in Form with Milliseconds

There are several examples of HTML5 form options on this page, including the "time" element. Is it possible to force the time element to include a millisecond component?
I'm not concerned for the fallback option where a plain text box is used.
This works:
<input type="time" step="0.001"></input>
Live preview: http://jsbin.com/giqikelumu/edit?html,output
Simply use the step attribute. In case of a input type="time". The step attribute defaults to 60 (1 means 1 second). But you can also set fractions.
<input type="time" step="any" />
As its an input tag, the value can be entered into it by the user then using the step attribute as stated above will surely help.
What if this input is in the form and value can come from some API cal and is given to the form to show it. It can be changed too. If the requirement then is to show or not show the second or millisecond part we can do the following.
When second and millisecond is required
getFormatDate = function (val) { // assuming val is date like "/Date(946673340000)/"
if (val != undefined) {
date = new Date(val.match(/\d+/)[0] * 1); // creating a date object from val
return new Date(date.getFullYear(), date.getMonth(), date.getDate(),
date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds());
}
}
When second and millisecond is NOT required
getFormatDate = function (val) { // assuming val is date like "/Date(946673340000)/"
if (val != undefined) {
date = new Date(val.match(/\d+/)[0] * 1); // creating a date object from val
return new Date(date.getFullYear(), date.getMonth(), date.getDate(),
date.getHours(), date.getMinutes());
}
}

How can you force HTML number input to show more than two decimal places?

So if someone entered 1.00, it would automatically format to 1.0000. Is this built into the numeric input in HTML 5?
I don't know of a way that's built into HTML.
However, it's easy enough to do in JavaScript.
element.addEventListener('change', function() {
var value = +this.value;
if (value === value) this.value = value.toFixed(4);
}, false);

How can I make the HTML5 number field display trailing zeroes?

I have a field:
<input type='number' />
I'd like to punch in 0.50 without it “correcting it” to 0.5, so it would display 0.50.
I attached an on('change') event to the input you want to have trailing 0's
$('.number-input').on('change', function(){
$(this).val(parseFloat($(this).val()).toFixed(2));
});
It just takes the value, casts it to a float, renders it to a string to the number of decimal places, and puts it back in as the value.
I've had a little play around with this and looked at the spec. It says that it must be a valid floating point number. There's one sentence in the definition of a valid floating point number it gives which caught my attention:
The best representation of the number n as a floating point number is
the string obtained from applying the JavaScript operator ToString to
n.
This means that the format will always be consistent with assessing what the number is, then using JavaScript's toString on that number. So no trailing 0s then.
So, you're going to have to resort to JavaScript. This isn't straightforward because document.getElementById('numInput').value = '0.50'; still gets corrected to 0.5, so the validation isn't triggered at onchange where the default action can be prevented, it's triggered internally.
This is the best solution I could come up with... it's a bit of a hack, and will need a bit of tweaking for robustness, but hopefully it'll do what you want:
var numInput = document.getElementById('numInput');
numInput.addEventListener('keypress', function () {
this.setAttribute('type', 'text');
});
numInput.addEventListener('click', function () {
this.setAttribute('type', 'number');
});
So if the user wants to enter the number by typing, it switches the input type to text, but when they click it, it converts it back to a number.
If you always want the trailing 0s no matter what the user types, then you could do it something like this:
var numInput = document.getElementById('numInput');
numInput.addEventListener('blur', function () {
if (this.value === '') {
return;
}
this.setAttribute('type', 'text');
if (this.value.indexOf('.') === -1) {
this.value = this.value + '.00';
}
while (this.value.indexOf('.') > this.value.length - 3) {
this.value = this.value + '0';
}
});
numInput.addEventListener('focus', function () {
this.setAttribute('type', 'number');
});
Edit: I think the second solution is more inline with what the user might expect, but it means that if the user types 0.5 it will be coerced to 0.50, so it depends if that's what you want.