This is what I've tried.
HTML:
<span *ngIf="!today" class="not-today">{{operation}}</span>
<span *ngIf="today" class="today">{{operation}}</span>
Component:
private today: any;
this.today = new Date().getTime();
I need to apply the span.today class only if it is today (.not-today to the spans that are not 'today') and this way I'm getting all spans with .not-today class. How can I achieve this?
Thanks.
Assuming your operation variable is an object and that object has a
property of type time and depending on what that time is relevant to
the present time you want to assign specific classes to your span
element.
There are two ways you can do this:
ngClass
One is to utilize the ngClass attribute by having a method return the relevant class, i.e:
getClassFromDate(date: Date) {
let match = date.getTime(); // convert date to number
let today = new Date().setHours(0,0,0,0); // get present day as number
let day = (n) => today + (86400000 * n); // assuming all days are 86400000 milliseconds, then add or remove days from today
if (match >= day(1) && match < day(2))
return 'tomorrow';
else if (match >= today && match < day(1))
return 'today';
else if (match < today && match > day(-2))
return 'yesterday';
else
return 'other';
}
And then in your template:
<span [ngClass]="getClassFromDate(operation.date)">{{operation.text}}</span>
Then of course include the relevant classes in your stylesheet:
.tomorrow {...}
.today {...}
.yesterday {...}
.other {...}
class.className
Your classes can also be appended like this:
<span [class.tomorrow]="tomorrow" [class.today]="today" [class.yesterday]="yesterday" [class.other]="!tomorrow && !today && !yesterday">{{operation}}</span>
In this case it takes a boolean and applies the class if the expression equates to true. Note however that you need to rewrite your logic for how the dates are handled.
You can read more about the difference between the two here. As a general rule of thumb, ngClass is for when you have several classes that should potentially be added and class.className is for when there is only one.
You can achieve in following way
Assume "operation" as string & "todayDate" as current date ((ie) actual scenario today date get from database).
Code look this
HTML:
<span [ngClass]="(getTodayClass()=== 'today') ? 'today' : 'not-today'">{{operation}}</span>
CSS:
<style>
.today {
background-color:red;
}
.not-today {
background-color:green;
}
Component:
//declaraion
todayDate: Date;
operation: string;
private sameDays(d1: Date, d2: Date) {
return d1.getUTCFullYear() == d2.getUTCFullYear() &&
d1.getUTCMonth() == d2.getUTCMonth() &&
d1.getUTCDate() == d2.getUTCDate(); //using UTC methods ensures that two equivalent days in different timezones matching
}
getTodayClass() {
//variable assign
this.todayDate = new Date; //this date get from database
this.operation = "Monday";
//check condition for database time and current time with help of UTC
if (this.sameDays(this.todayDate, new Date)) {
return 'today';
} else {
return 'not-today';
}
}
Hope this was helpful for your expectation
Related
A friend of mine is attending a JavaScript course and thinks that the code he is submitting for grading is correct. However, the grader support keeps reporting it as not correct. He asked for my help and I tested the code on several IDEs and editors, online and offline, and I also got back every time a correct evaluation.
However I don't use often JavaScript ans I'm hesitating to answer my friend that he is right.
I would be most grateful if someone with more experience could tell me if the code evaluates correctly or not. Thank you.
"Determines which day of the week had the most nnumber of people visiting the pet store.
If more than one day of the week has the same, highest amount of traffic, an array containing the days (in any order) should be returned.
(ex. ["Wednesday", "Thursday"]).
If the input is null or an empty array, the function should return null.
#param week an array of Weekday objects
#return a string containing the name of the most popular day of the week if there is only one most popular day, and an array of the strings containing the names of the most popular days if there are more than one that are most popular"
function Weekday (name, traffic) {
this.name = name;
this.traffic = traffic;
}
function mostPopularDays(week) {
// IMPLEMENT THIS FUNCTION!
this.week = week;
if (typeof week !== 'object' || week === null || week === undefined || week.length === 0) {
return null;
}
var maxTr = 0;
var maxTrDay = [];
for (var i = 0; i < this.week.length; i++) {
if (this.week[i].traffic > maxTr) {
maxTrDay = [this.week[i].name];
//maxTrDay = this.week[i].name;
maxTr = this.week[i].traffic;
} else if (this.week[i].traffic === maxTr) {
//maxTrDay = [this.week[i].name];
maxTrDay.push(this.week[i].name);
} else if (this.week.length > 7) {
this.week.shift();
}
}
if (maxTrDay.length === 1) {
console.log("The most popular day of the week was:")
return maxTrDay[0];
} else if (maxTrDay > 1) {
console.log("The most popular days of the week were:")
return maxTrDay;
}
return null;
}
The test case that the grader reports as failed are the following:
1. mostPopularDays should return an array of days when more than one day has most popular traffic
I used the following lines for testing, and the output was always the last (commented) line below:
var week = [];
var sun = new Weekday('Sunday', 100); week.push(sun);
var mon = new Weekday('Monday', 90); week.push(mon);
var tue = new Weekday('Tuesday', 100); week.push(tue);
mostPopularDays(week);
// [Sunday, Tuesday]
The issue is (maxTrDay > 1) is comparing an array object with the number 1. This will be false for all array inputs except for, confusingly, e.g. ([2] > 1), but that's JS for you.
Running your code as-is with the provided driver (with added quotes to Tuesday to avoid a ReferenceError) yields the output of null.
Your friend probably means (maxTrDay.length > 1), which compares based on length and yields the correct output:
The most popular days of the week were:
=> [ 'Sunday', 'Tuesday' ]
Update:
I have several objects with start dates and end date
When inserting / modifying an object, the starting or ending date of the new object can not be included in the existing object.
Exist : 06/06/2018-----30/06/2018
can input:
04/06/2018-------05/06/2018
02/02/2018------ until less than date Start of which exists (05/06/2018)
or higher:
31/06/2018--------
can not get in :
04/06/2018-------07/06/2018 The end is already understood between the beginning and the end exists.
Or
07/06/2018---08/06/2018 because it is also included between the beginning and the end of the.
Code:
validateParamsDates(url, newConfig) {
return this.http.get<any>(url).pipe(map(param => {
let messageError = { message: "", showAlert: false };
let userStart = newConfig.startdatevalidity;
let userFinish = newConfig.enddatevalidity;
param[1]['params'].array.forEach(element => {
if(userStart > element.startdatevalidity && userFinish > element.enddatevalidity
|| userStart < element.startdatevalidity && userFinish < element.enddatevalidity
&& userStart > element.enddatevalidity
){
console.log('good');
}else{
console.log('=(');
}
});
return messageError ;
}));
}
You should first convert the strings to a Date object. Then you can compare dates and everything will work as it should ;)
So you would do something like:
const start2: Date = new Date(Object2.start);
const end1: Date = new Date(Object1.end);
if (start2 > end1) { console.log('good'); }
Please also note that in order for all of this to work in javascript, the dates should be defined in MM/DD/YYYY format not in DD/MM/YYYY
I would probably do something like this.
var start = new Date(Object2.start);
var end = new Date(Object1.end);
if(start.getTime() > end.getTime()) console.log('good');
Similar to this answer: Compare two dates with JavaScript
I was looking everywhere, but I couldn't find a good code for my problem.
I have some input fields, what the users are using to send online their requests.
And one of the fields is a date field, what I would like somehow to validate in that way, that to be allowed only if the entered date to be somewhere between today and 8 days before.
Example: if today is 29 November , they would be allowed to enter only date between 21st-29th November and nothing else
And to be shown an alert window already when they have entered the wrong date
They will pick up the days from minicalendar but that part is resolved, I need help only with the validating.
If somebody could post a working code, I would be very grateful.
Thank you
Use jQuery UI DatePicker, the script below:
$(function() {
var currentDate = new Date();
var maxAllowedDate = new Date(currentDate);
maxAllowedDate.setDate(currentDate.getDate() + 8);
$( "#datepicker" ).datepicker({
changeYear: true,
minDate: '0',
maxDate: '+7D',
});
$('#datepicker').change(function(){
var enteredVal = new Date(this.value);
if(enteredVal.getTime() < currentDate.getTime() || enteredVal.getTime() > maxAllowedDate.getTime()) {
alert("invalid");
} else {
alert("valid");
}
});
});
and the UI:
<div class="demo">
<p>Date: <input type="text" id="datepicker"></p>
Here is the jsFiddle demo: http://jsfiddle.net/pjkz7k0t/1/
Since you asked for javascript, I will assume you want a javascript answer, not a jQuery answer.
function isValidDate(checkDate) {
if(/\d\d\/\d\d\/\d\d\d\d/.test(checkDate)) {
// split checkDate into three pieces
var strMM = checkDate.split('/')[0];
var strDD = checkDate.split('/')[1];
var strYYYY = checkDate.split('/')[2];
// create new Date() object from split pieces
var strDateCheck = new Date(strYYYY,(strMM - 1),strDD);
// evaluate each piece of resulting date object against each corresponding piece of checkDate
if(((strDateCheck.getMonth() + 1) == strMM) && (strDateCheck.getDate() == strDD) && (strDateCheck.getFullYear() == strYYYY)) {
/* if you wish, add additional validation constraints here */
return true; // all three pieces match exactly
}
}
return false; // did not meet criteria for return true
}
This method uses explicit regex to validate the formats.
Instead of creating elaborate methods of testing each piece, I used the pieces to build a new Date() object, knowing that the result MIGHT not match checkDate, and used pieces from resulting date to test the pieces of checkDate passed into the function. If ALL THREE pieces match, the entered date is valid.
For instance:
'02/29/2014' returns false
'02/29/2012' returns true
'12/36/2014' returns false
'29/06/2014' returns false
The code is pure javascript which improves portability, and this method does not interfere or impede additional validation by any other criteria you choose to use (against year ranges, or evaluating strCheckDate against today(), or any other constraints specific to your specific application).
An added advantage is that this method does not just determine whether what is passed to the function can be used to create a valid date, but confirms that the date entered MATCHES the valid date that can be created (thereby overcoming the problem of javascript rolling "extra days" forward on date creation).
This could easily be expanded to test for various configurations of date, using the exact same logic, simply by creating a different regex test, and splitting checkDate differently.
regex for DD/MM/YYYY would be the same, but the split would look like this:
// split characters into three pieces
var strDD = checkDate.split('/')[0];
var strMM = checkDate.split('/')[1];
var strYYYY = checkDate.split('/')[2];
Or for YYYY/MM/DD you would use regex:
/\d\d\d\d\/\d\d\/\d\d/.test(checkDate)
and the split would look like this:
// split characters into three pieces
var strYYYY = checkDate.split('/')[0];
var strMM = checkDate.split('/')[1];
var strDD = checkDate.split('/')[2];
This is highly morphable (and clean) javascript code to accomplish the purpose of validating a user entered date, and can be quickly modified to expand checks for valid date within range.
function isValidDateRange(checkDate,minDate,maxDate) {
if(/\d\d\/\d\d\/\d\d\d\d/.test(checkDate)) {
// split checkDate into three pieces
var strMM = checkDate.split('/')[0];
var strDD = checkDate.split('/')[1];
var strYYYY = checkDate.split('/')[2];
// create new Date() object from split pieces
var strDateCheck = new Date(strYYYY,(strMM - 1),strDD);
// evaluate each piece of resulting date object against each corresponding piece of checkDate
if(((strDateCheck.getMonth() + 1) == strMM) && (strDateCheck.getDate() == strDD) && (strDateCheck.getFullYear() == strYYYY)) {
// if this code fires, you have a valid date entered, first logic hurdle passed
// If you pass in minDate and maxDate as any format other than a date object, you should
// create new Date(); from them before comparing.
// Example:
// var strMinMM = minDate.split('/')[0];
// var strMinDD = minDate.split('/')[1];
// var strMinYYYY = minDate.split('/')[2];
// minDate = new Date(strMinYYYY,(strMinMM - 1),strMinDD);
// var strMaxMM = maxDate.split('/')[0];
// var strMaxDD = maxDate.split('/')[1];
// var strMaxYYYY = maxDate.split('/')[2];
// maxDate = new Date(strMaxYYYY,(strMaxMM - 1),strMaxDD);
if((!strDateCheck < minDate) && (!strDateCheck > maxDate)) {
return true; // all three pieces match exactly AND date is within specified range
}
}
}
return false; // did not meet criteria for return true
}
I have an input field that allows a user to enter a date.
I need this date to be in the following format: 10Jan13 (capitalization is not important)
There is a popup calender that if used will format the date correctly for the user.
I'd like to check the value of the input onblur using Javascript to be sure that the user did not either paste or type the date improperly.
I am currently checking number-only fields like this:
var numbers = /^[0-9]+$/;
if (!BIDInput.value.match(numbers))
{
checkedInput.value = "";
alert('Not a number');
}
and I'm checking letters-only fields like this:
var letters = /^[a-z]+$/
if (!nameInput.value.match(letters))
{
nameInput.value = "";
alert('Not a letter');
}
I would like to check the date format in a similar a fashion if possible. But anything that accomplishes the task will do. Can anyone point me in the right direction on how to get this done?
I know that client side validation does not replace server side validation. This is for user experience purposes only.
You're pretty much there with what you have. Basically your format is one or two digits, then one of 12 possible strings, followed by two digits. So for instance:
var shortDateRex = /^\d{1,2}(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\d{2}$/;
Breakdown:
^ Start of string.
\d{1,2} One or two digits.
(:?...) A non-capturing group. Or you could use a capture group if you like.
Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec An alternation, allowing any of those twelve choices. Naturally you can add more if you like. If you have two choices that start the same way (Jan and January, for instance), put the longer one earlier in the alternation.
\d{2} Two digits.
Side note: I'd have to recommend against two-digit dates on principle, and particularly given where in the century we currently are!
Responding to Amberlamps' comment that this doesn't validate the date: Once you've validated the format, it's trivial to then check the date itself if you like (to rule out 30Feb13, for instance):
var validateDateString = (function() {
var monthNames = "Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec".toLowerCase().split("|");
var dateValidateRex = /^(\d{1,2})(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)(\d{2})$/i;
var arbitraryCenturyCutoff = 30;
function validateDateString(str) {
var match;
var day, month, year;
var dt;
match = dateValidateRex.exec(str);
if (!match) {
return false;
}
day = parseInt(match[1]);
month = monthNames.indexOf(match[2].toLowerCase()); // You may need a shim on very old browsers for Array#indexOf
year = parseInt(match[3], 10);
year += year > arbitraryCenturyCutoff ? 1900 : 2000;
dt = new Date(year, month, day);
if (dt.getDate() !== day ||
dt.getMonth() !== month ||
dt.getFullYear() !== year) {
// The input was invalid; we know because the date object
// had to adjust something
return false;
}
return true;
}
return validateDateString;
})();
...or something along those lines.
Live Example | Source
Or if (like me) you hate to see a list like that list of month names repeated you can use the RegExp constructor with a string instead, but you have to remember to duplicate your backslashes:
var monthNamesString = "Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec";
var monthNames = monthNamesString.toLowerCase().split("|");
var dateValidateRex = new RegExp("^(\\d{1,2})(" + monthNamesString + ")(\\d{2})$", "i");
Live Example | Source
You would use the following regular expression to check for a string starting with 2 numbers, followed by 3 characters followed by 2 numbers
[0-9]{2}[a-zA-Z]{3}[0-9]{2}
I have a list of job postings and would like to display a div that say 'New' when the date is equal to today's date.
To create this I have created a javascript code that will execute on a loop for each set of outer div's, but I am having trouble correctly running the .each function.
Here is the link to a JSFiddle: http://jsfiddle.net/jeremyccrane/2p9f7/
Here is the HTML Code:
<div class="outer">
<div class="job-date">07-Feb-13</div>
<div class="new" style="display:none;">NEW</div>
<div class="value"></div>
</div>
<div class="outer">
<div class="job-date">12-Feb-13</div>
<div class="new" style="display:none;">NEW</div>
<div class="value"></div>
</div>
Here is the Javascript code:
$( ".outer" ).each(function(i) {
var jd = $(".job-date").text();
j = jd.substr(0,2);
var today = new Date();
var dd = ( '0' + (today.getDate()) ).slice( -2 )
$('.value').html(dd + "/" + j);
if(dd === j) {
$('.new').show();
} else {
$('.new').show();
}
return false;
});
Not too sure what you think the problem is but I could see a couple of issues. Mainly, when you do for example:
$('.new').show();
you're calling show() on ALL matching elements of class new, not just the one 'under' the outer you're in. Try this:
$('.new', this).show();
You were setting the new to show whichever way your date comparison went too. I had a stab at updating your fiddle below:
$( ".outer" ).each(function(i) {
var jd = $(".job-date", this).text();
j = jd.substr(0,2);
var today = new Date();
var dd = ( '0' + (today.getDate()) ).slice( -2 )
$('.value', this).html(dd + "/" + j);
if(dd === j) {
$('.new', this).show();
} else {
// $('.new', this).show();
// do something different here
}
});
This code appears to do what you want:
$(".outer").each(function(i) {
var jd = $(this).find(".job-date").text();
var j = jd.substr(0,2);
var today = new Date();
var dd = ('0' + (today.getDate())).slice(-2);
$(this).find('.value').html(dd + "/" + j);
if(dd == j) {
$(this).find('.new').show();
} else {
$(this).find('.new').hide();
}
return false;
});
http://jsfiddle.net/Dk4dQ/
Your main problem was that you were missing all of the $(this).find() calls. You are iterating through containers. Using $(this).find() will get you the controls within those containers. The plain $() calls will find all matching elements in the document, which is not what you want.
The this in this case refers to the container. Wrapping it in the jQuery function lets us use the jQuery find method to get it's children.
Also, as the others mentioned, you were show()ing the div regardless of success or failure, which again is not what you want.
You have 2 problems here. First of all, you're triggering show() regardless of whether the dates match or not:
if(dd === j) {
$('.new').show();
} else {
$('.new').show(); // <-- shouldn't show in this case
}
The second problem is that you're showing everything with the class "new", when you only want to show particular divs. You'll need to give unique IDs to each "new" div, and then fix your code to only show the divs with that particular ID.
You don't need a complicated iterator function. All you need is:
$(".outer .job-date" ).filter(function() {
return (Date.parse($(this).text()) / 86400000 | 0) == (new Date() / 86400000 | 0);
}).next().show();
filter seems like a better choice for what you're doing than each. First we just want the set of elements that have a date equal to today.
To do that we can take the dates and get rid of the time part. Dates are represented in terms of number of milliseconds since the epoch. By dividing by the number of milliseconds in a day (86400000, or 60*60*24*1000) and then truncating any decimal part (javascript idiom: |0) we are comparing the number of full days since the epoch.
Now with a set of elements containing today's date, next() advances every matched element to the next sibling (the hidden div with class new), and show() shows it.