I have a page that shows a javascript countdown. The javascript automatically populates "d" for days, "h" for hours, etc... CSS adds "ay(s)", "our(s)", etc..., as space allows, and capitalizes them.
Javascript:
function cdtd(broadcast) {
var nextbroadcast = new Date(broadcast);
var now = new Date();
var timeDiff = nextbroadcast.getTime() - now.getTime();
if (timeDiff <= 0) {
clearTimeout(timer);
document.getElementById("countdown").innerHTML = "<a href=\"flconlineservices.php\">Internet broadcast in progress<\/a>";
/* Run any code needed for countdown completion here */
}
var seconds = Math.floor(timeDiff / 1000);
var minutes = Math.floor(seconds / 60);
var hours = Math.floor(minutes / 60);
var days = Math.floor(hours / 24);
hours %= 24;
minutes %= 60;
seconds %= 60;
document.getElementById("daysBox").innerHTML = days + " d";
document.getElementById("hoursBox").innerHTML = hours + " h";
document.getElementById("minsBox").innerHTML = minutes + " m";
// seconds isn't in our html code (javascript error if this isn't commented out)
/*document.getElementById("secsBox").innerHTML = seconds + " s";*/
var timer = setTimeout('cdtd(broadcast)',1000);
}
CSS:
[role="navigation"] {text-transform:capitalize;}
#media screen and (min-width:1600px) {
#countdown #daysBox:after {content:"ay(s)";}
#countdown #hoursBox:after {content:"our(s)";}
#countdown #minsBox:after {content:"inute(s)";}
}
Firefox and Opera display the countdown as I expected (3 Day(s), 5 Hour(s), etc...), but Internet Explorer capitalizes the (s) (3 Day(S), 5 Hour(S), etc...). Safari and Chrome are even worse, as they capitalize the (s) and the first letter of the CSS generated content (3 DAy(S), 5 HOur(S), etc...).
I found a page that shows typography bugs with :first-letter and :first-line that may be somewhat related.
I tried doing text-transform:lowercase and then text-transform:capitalize, but that didn't change the results.
Any ideas on how to fix this? I'll probably just knock out the capitalization, but then I have to make sure everything is typed in the correct casing.
JJ
Ok so from what I can tell you just need the first letter of days, hours and minutes caps. You can do this in javascript. Something like
var daysString = days + " d";
document.getElementById("daysBox").innerHTML = daysString.toUpperCase();
Update: forgot to mention take our #countdown {text-transform:capitalize;}
Related
been trying to use the later.js with no luck here is how i do it
var hour = document.getElementById("starthour").value;
var minute= document.getElementById("startminute").value;
var time = "'0 "+ minute +" " + hour + " " + "? * SUN-THU'";
var s = later.parse.cron(time);
var timer = later.setInterval(checkWhoIsMissing, s);
help will be appreciated
to answer my own question
there was a problem with my time definition
best way to figure out a time is to look at
http://www.nncron.ru/help/EN/working/cron-format.htm
in general the format should be
Minute Hour Dayofthemonth Monthoftheyear DayoftheWeek
if you don't use one of them you need to put a star instead
sample
0 16 * * 0-5
which yields
16:00 on sun through Friday every month every year
another thing that helps is
to write a simple schedule
for example
var results = later.schedule(s).next(5);
for (var i = 0; i < results.length; i++) {
alert( results[i].toLocaleString());
}
so you can see right away what are the next scheduled times.
hope that helps
"Be well do good keep in touch"
I'm using the fullcalendar resourceviews fork version 1.6.1.6...
I used an older version which had the resources on the top and the times on the left axis.
But now it is different. The times are on the top and the resources are on the left axis. It's not that good anymore. Is there a way to change it?
I need the newer version of it because of the refetchResources function.
I modified the resource object (using Ike Lin fullCalendar) and added an array which includes the number of the day, start time and end time like 0 -> 09:00 -> 12:00, 1 10:00 -> 15:30 ...
Then I changed the fullcalendar.js
function updateCells() {
var i;
var headCell;
var bodyCell;
var date;
var d;
var maxd;
var today = clearTime(new Date());
for (i=0; i<colCnt; i++) {
date = resourceDate(i);
headCell = dayHeadCells.eq(i);
if(resources[i].anwesenheit[date.getDay()-1] != null){
var von = resources[i].anwesenheit[date.getDay()-1].von;
var _von = von.substring(0, 5);
var bis = resources[i].anwesenheit[date.getDay()-1].bis;
var _bis = bis.substring(0, 5);
headCell.html(resources[i].name + "<p style='font-weight: normal; font-size: 11px;'>" + _von + " - " + _bis + " Uhr</p>");
} else {
headCell.html(resources[i].name);
}
headCell.attr("id", resources[i].id);
bodyCell = dayBodyCells.eq(i);
if (+date == +today) {
bodyCell.addClass(tm + '-state-highlight fc-today');
}else{
bodyCell.removeClass(tm + '-state-highlight fc-today');
}
setDayID(headCell.add(bodyCell), date);
}
}
This shows the work time from each resource right unter the name of the resource.
Also I added a serverside function to the select function which checks if the resource is available. If yes, then the event will be created, else the event won't be created and I get an error message.
Now I can work with it. It's not exactly what I wanted, but it's nice to use now. It updates the times under the resource name on every day change so I have an overview when a resource is available and when it's not available.
I'm trying to implement this solution to "grey out" past events in Fullcalendar, but I'm not having any luck. I'm not too well versed in Javascript, though, so I assume I'm making some dumb mistakes.
I've been putting the suggested code into fullcalendar.js, inside the call for daySegHTML(segs) around line 4587.
I added the first two lines at the end of the function's initial var list (Why not, I figured)—so something like this:
...
var leftCol;
var rightCol;
var left;
var right;
var skinCss;
var hoy = new Date;// get today's date
hoy = parseInt((hoy.getTime()) / 1000); //get today date in unix
var html = '';
...
Then, just below, I added the other two lines inside the loop:
for (i=0; i<segCnt; i++) {
seg = segs[i];
event = seg.event;
classes = ['fc-event', 'fc-event-skin', 'fc-event-hori'];
if (isEventDraggable(event)) {
classes.push('fc-event-draggable');
}
unixevent = parseInt((event.end.getTime()) / 1000); //event date in Unix
if (unixevent < hoy) {classes.push('fc-past');} //add class if event is old
if (rtl) {
if (seg.isStart) {
classes.push('fc-corner-right');
}
...
Running this code results in a rendered calendar with no events displayed and an error message: Uncaught TypeError: Cannot call method 'getTime' of null
The "null" being referred to is, apparently, event.end.getTime(). But I'm not sure I understand what exactly is going wrong, or how things are being executed. As written, it seems like it should work. At this point in the code, from what I can tell, event.end contains a valid IETF timecode, but for some reason it's "not there" when I try to run it through getTime()?
This isn't a mission-critical tweak for me, but would still be nice—and I'd like to understand what's going on and what I'm doing wrong, as well! Any help greatly appreciated!
If you are using FullCalendar2 with Google Calendar, you will need to use the version of the code below. This uses Moment.js to do some conversions, but since FC2 requires it, you'll be using it already.
eventRender: function(event, element, view) {
var ntoday = new Date().getTime();
var eventEnd = moment( event.end ).valueOf();
var eventStart = moment( event.start ).valueOf();
if (!event.end){
if (eventStart < ntoday){
element.addClass("past-event");
element.children().addClass("past-event");
}
} else {
if (eventEnd < ntoday){
element.addClass("past-event");
element.children().addClass("past-event");
}
}
}
As per FullCalendar v1.6.4
Style past events in css:
.fc-past{background-color:red;}
Style future events in css:
.fc-future{background-color:red;}
There's no need to fiddle with fullcalendar.js. Just add a callback, like:
eventRender: function(calev, elt, view) {
if (calev.end.getTime() < sometime())
elt.addClass("greyclass");
},
you just have to define the correct CSS for .greyclass.
Every event has an ID associated with it. It is a good idea to maintain your own meta information on all events based on their ids. If you are getting the events popupated from a backend database, add a field to your table. What has worked best for me is to rely on callbacks only to get the event ids and then set/reset attributes fetched from my own data store. Just to give you some perspective, I am pasting below a section of my code snippet. The key is to target the EventDAO class for all your needs.
public class EventDAO
{
//change the connection string as per your database connection.
//private static string connectionString = "Data Source=ASHIT\\SQLEXPRESS;Initial Catalog=amit;Integrated Security=True";
//this method retrieves all events within range start-end
public static List<CalendarEvent> getEvents(DateTime start, DateTime end, long nParlorID)
{
List<CalendarEvent> events = new List<CalendarEvent>();
// your data access class instance
clsAppointments objAppts = new clsAppointments();
DataTable dt = objAppts.SelectAll( start, end);
for(int i=0; i<dt.Rows.Count; ++i)
{
CalendarEvent cevent = new CalendarEvent();
cevent.id = (int)Convert.ToInt64(dt.Rows[i]["ID"]);
.....
Int32 apptDuration = objAppts.GetDuration(); // minutes
string staffName = objAppts.GetStaffName();
string eventDesc = objAppts.GetServiceName();
cevent.title = eventDesc + ":" + staffName;
cevent.description = "Staff name: " + staffName + ", Description: " + eventDesc;
cevent.start = (DateTime)dt.Rows[i]["AppointmentDate"];
cevent.end = (DateTime) cevent.start.AddMinutes(apptDuration);
// set appropriate classNames based on whatever parameters you have.
if (cevent.start < DateTime.Now)
{
cevent.className = "pastEventsClass";
}
.....
events.Add(cevent);
}
}
}
The high level steps are as follows:
Add a property to your cevent class. Call it className or anything else you desire.
Fill it out in EventDAO class while getting all events. Use database or any other local store you maintain to get the meta information.
In your jsonresponse.ashx, retrieve the className and add it to the event returned.
Example snippet from jsonresponse.ashx:
return "{" +
"id: '" + cevent.id + "'," +
"title: '" + HttpContext.Current.Server.HtmlEncode(cevent.title) + "'," +
"start: " + ConvertToTimestamp(cevent.start).ToString() + "," +
"end: " + ConvertToTimestamp(cevent.end).ToString() + "," +
"allDay:" + allDay + "," +
"className: '" + cevent.className + "'," +
"description: '" +
HttpContext.Current.Server.HtmlEncode(cevent.description) + "'" + "},";
Adapted from #MaxD The below code is what i used for colouring past events grey.
JS for fullcalendar pulling in Json
events: '/json-feed.php',
eventRender: function(event,element,view) {
if (event.end < new Date().getTime())
element.addClass("past-event");
},
other options ....
'event.end' in my Json is a full date time '2017-10-10 10:00:00'
CSS
.past-event.fc-event, .past-event .fc-event-dot {
background: #a7a7a7;
border-color: #848484
}
eventDataTransform = (eventData) => {
let newDate = new Date();
if(new Date(newDate.setHours(0, 0, 0, 0)).getTime() > eventData.start.getTime()){
eventData.color = "grey";
}else{
eventData.color = "blue";
}
return eventData;
}
//color will change background color of event
//textColor to change the text color
Adapted from #Jeff original answer just simply check to see if an end date exists, if it does use it otherwise use the start date. There is an allDay key (true/false) but non allDay events can still be created without an end date so it will still throw an null error. Below code has worked for me.
eventRender: function(calev, elt, view) {
var ntoday = new Date().getTime();
if (!calev.end){
if (calev.start.getTime() < ntoday){
elt.addClass("past");
elt.children().addClass("past");
}
} else {
if (calev.end.getTime() < ntoday){
elt.addClass("past");
elt.children().addClass("past");
}
}
}
Ok, so here's what I've got now, that's working (kind of):
eventRender: function(calev, elt, view) {
var ntoday = new Date();
if (calev.start.getTime() < ntoday.getTime()){
elt.addClass("past");
elt.children().addClass("past");
}
}
In my stylesheet, I found I needed to restyle the outer and inner elements to change the color; thus the elt.children().addclass addition.
The only time check I could get to work, lacking an end time for all day events, was to look at the start time - but this is going to cause problems with multi-day events, obviously.
Is there another possible solution?
I've read conflicting information regarding Internet Explorer's silly CSS limits. I am (think I am) understanding that you can only have 31 <style> and <link> tags (combined), and that each sheet can have up to 31 #import-s (so 31 <link>-s, each to 31 #import-s is fine, albeit insane).
However, the 4095 rule is less clear - is this 4095 rules per document, or per sheet? For instance, can I <link> to two stylesheets, each with 4000 rules, and have it work, or will this break the limit?
3rd party edit 2018
On this msdn blog post stylesheet-limits-in-internet-explorer further information is given.
Referring the following from Microsoft:
Stylesheet Limits in Internet Explorer
KB - A webpage that uses CSS styles does not render correctly in Internet Explorer
The rules for IE9 are:
A sheet may contain up to 4095 selectors (Demo)
A sheet may #import up to 31 sheets
#import nesting supports up to 4 levels deep
The rules for IE10 are:
A sheet may contain up to 65534 selectors
A sheet may #import up to 4095 sheets
#import nesting supports up to 4095 levels deep
Testing the 4095 rule by sheet limit
By way of confirmation, I've created a gist with 3 files. One HTML, and two CSS files.
The first file contains 4096 selectors and means that its final selector doesn't get read in.
The second file (4095.css) has one less selector, and gets read in, and works perfectly in IE (even though its already read another 4095 selectors from the previous file.
A javascript script to count your CSS rules:
function countCSSRules() {
var results = '',
log = '';
if (!document.styleSheets) {
return;
}
for (var i = 0; i < document.styleSheets.length; i++) {
countSheet(document.styleSheets[i]);
}
function countSheet(sheet) {
if (sheet && sheet.cssRules) {
var count = countSelectors(sheet);
log += '\nFile: ' + (sheet.href ? sheet.href : 'inline <style> tag');
log += '\nRules: ' + sheet.cssRules.length;
log += '\nSelectors: ' + count;
log += '\n--------------------------';
if (count >= 4096) {
results += '\n********************************\nWARNING:\n There are ' + count + ' CSS rules in the stylesheet ' + sheet.href + ' - IE will ignore the last ' + (count - 4096) + ' rules!\n';
}
}
}
function countSelectors(group) {
var count = 0;
for (var j = 0, l = group.cssRules.length; j < l; j++) {
var rule = group.cssRules[j];
if (rule instanceof CSSImportRule) {
countSheet(rule.styleSheet);
}
if (rule instanceof CSSMediaRule) {
count += countSelectors(rule);
}
if( !rule.selectorText ) {
continue;
}
count += rule.selectorText.split(',').length;
}
return count;
}
console.log(log);
console.log(results);
};
countCSSRules();
I don't have enough rep to comment on the above similar snippet, but this one counts the #media rules. Drop it in Chrome console.
function countCSSRules() {
var results = '',
log = '';
if (!document.styleSheets) {
return;
}
for (var i = 0; i < document.styleSheets.length; i++) {
countSheet(document.styleSheets[i]);
}
function countSheet(sheet) {
var count = 0;
if (sheet && sheet.cssRules) {
for (var j = 0, l = sheet.cssRules.length; j < l; j++) {
if (!sheet.cssRules[j].selectorText) {
if (sheet.cssRules[j].cssRules) {
for (var m = 0, n = sheet.cssRules[j].cssRules.length; m < n; m++) {
if(sheet.cssRules[j].cssRules[m].selectorText) {
count += sheet.cssRules[j].cssRules[m].selectorText.split(',').length;
}
}
}
}
else {
count += sheet.cssRules[j].selectorText.split(',').length;
}
}
log += '\nFile: ' + (sheet.href ? sheet.href : 'inline <style> tag');
log += '\nRules: ' + sheet.cssRules.length;
log += '\nSelectors: ' + count;
log += '\n--------------------------';
if (count >= 4096) {
results += '\n********************************\nWARNING:\n There are ' + count + ' CSS rules in the stylesheet ' + sheet.href + ' - IE will ignore the last ' + (count - 4096) + ' rules!\n';
}
}
}
console.log(log);
console.log(results);
};
countCSSRules();
source: https://gist.github.com/krisbulman/0f5e27bba375b151515d
According to a page on the MSDN IEInternals blog entitled Stylesheet Limits in Internet Explorer the limits shown above (31 sheets, 4095 rules per sheet, and 4 levels) applied to IE 6 through IE 9. The limits were increased in IE 10 to the following:
A sheet may contain up to 65534 rules
A document may use up to 4095 stylesheets
#import nesting is limited to 4095 levels (due to the 4095 stylesheet limit)
A nice solution to this problem for people using Grunt:
https://github.com/Ponginae/grunt-bless
Developer tools within FireFox dev edition shows CSS rules
Might be handy for those of you still fighting with older IE versions / large CSS files.
FF Developer Edition Website
I think it's also worth noting that any CSS file larger than 288kb will only be read up until that ~288kb. Anything after will be completely ignored in IE <= 9.
http://joshua.perina.com/africa/gambia/fajara/post/internet-explorer-css-file-size-limit
My advice is to keep CSS files for larger applications split up into modules & components and keep a constant eye on filesize.
I want to show some effect (animate) with the help of jQuery during the time that should be calculated based on how many results are found for a particular needle. The rule is that the effect should continue no longer than 5 minutes and at the very least be 5 seconds long.
So, here's what I do in particular. I search a database for a particular word the user inputs and count the results. Then I search a myself defined word in the same database and count the results. If there are more the latter results than the former results, I need to calculate how long to show the effect. The more the latter results found, the longer the time the effect should continue. Plus, I need to obey the rule: no longer than 5 minutes, no less than 5 seconds.
I need that to be accurate at best.
That may be a stupid question but I cannot figure out on my own how to calculate the time! :)
http://jsfiddle.net/rCVnv/3/
$(function(){
var firstNum = Math.random()*10000,
secondNum = Math.random()*10000,
result = parseInt(secondNum - firstNum),
milli = 0;
if(result > 0){
if(result < 300000 && result > 5000){
milli = result;
$("#test").fadeOut(result);
}else if(result > 300000){
milli = 300000;
}else if(result < 5000){
milli = 5000;
}
$("#test").fadeOut(milli);
}
$("#result").text("Result : " + result);
});
Im not really sure how you will calculate the milliseconds needed. What I do here is generate 2 random numbers, and subtract the first value from the second value. If the result is between 300000 milliseconds (5 minutes) and 5000 milliseconds, then it just fades it at that number. If it falls beyond those ranges, it sets it to either the high end or low end. Of course, if the result is negative nothing happens because value 1 was larger than value 2.
Also I used fadeOut, which can easily be replaced with animate.
var intSecondsPerResult = 2;
var intAnimationDuration = intSecondsPerResult*{$intResultsCount};
if(intAnimationDuration < 5) {
intAnimationDuration = 5;
} else if(intAnimationDuration > 300) {
intAnimationDuration = 300;
}
PS: $intResultsCount contains the size of your resultset
That is what you want?