FullCalendar - is it possible to change the position of the end time? - javascript

Well looking at the code, I couldn't find a very simple way to do this. The reason is, when you add the end time it is added to the start time span, so here is the solution I came up with:
$('#cal').fullCalendar({
'events': test,
'timeFormat': 'H:mm - {H:mm}'
});
$('.fc-event-time').each(function() {
var obj = $(this);
var parent = $(this).parent();
var time = $(this).text();
var start = time.split(' - ')[0];
var finish = time.split(' - ')[1];
obj.text(start);
parent.append('<span class="fc-event-time" style="float: right;">' + finish + '</span>');
});
See it working here
To start with, add the 'timeFormat' to the calendar (I'll assume you already have it to be displaying the finish time), give the times a separator - (this will allow splitting of the two times)
Note any time inside the {} will be the finish time.
Next get jQuery to loop through each element with the class fc-event-time (which is added to the time by fullCalendar).
Now we need to get hold of the parent of the time so we can add an element to it later.
Next get the time and separate on - (space dash space)
Now set the original holder that had both start and finish so it is just the start.
Now add another span element to the parent, which is the header of the event, but float it to the right and add the finish time.
As per justkt's comments, it made me think, the method posted above would only run on page load, so when you changed the view, it wouldn't run again.
To solve that, add a callback when the events are rendered:
$('#cal').fullCalendar({
'events': test,
'eventRender' : renderEvents,
'timeFormat': 'H:mm - {H:mm}',
});
function renderEvents(){
$('.fc-event-time').each(function() {
var obj = $(this);
if (!obj.hasClass('finish-moved')) {
var parent = $(this).parent();
var time = $(this).text();
var start = time.split(' - ')[0];
var finish = time.split(' - ')[1];
obj.text(start);
parent.append('<span class="fc-event-time finish-moved" style="float: right;">' + finish + '</span>');
obj.addClass('finish-moved');
}
});
}
See it working here
This needed a little more logic adding to it, event render appears to be called for each event, so when the finish time span is added, the next time the loop runs it would try to split finish time, so stop that add a class finish-moved so that it isn't affected again.
Another update as per justkt's comments again:
When the callback is called it will pass the object it is affecting, so you can 'operate' on just that, instead of running multiple loops:
$('#cal').fullCalendar({
'events': test,
'eventRender': renderEvents,
'timeFormat': 'H:mm - {H:mm}',
});
function renderEvents(e, a) {
var startObj = $(a).find('.fc-event-time');
var time = $(startObj).text().split(' - ');
$(startObj).text(time[0]);
$(a).find('.fc-event-inner').append('<span class="fc-event-time" style="float: right;">' + time[1] + '</span>');
}
See it working here
It is a very similar principal, just just operates on the event which has called the callback so should be less resource hungry.

Related

Collection Boolean isn't being set to false - Meteor

So in short, the app that i'm developing is a bus timetable app using Meteor, as a practice project.
inside my body.js, I have an interval that runs every second, to fetch the current time and compare to items in a collection.
To show relevant times, I have added an isActive boolean, whenever the current time = sartTime of the collection, it sets it to true, and that is working fine.
But when I do the same thing for endTime and try to set it to false, so I can hide that timeslot, it just doesn't work. Even consoles don't show up. What am I missing? I have recently just started doing meteor, so excuse the redundancies.
Worth noting that the times that I'm comparing to are times imported from an CSV file, so they have to be in the 00:00 AM/PM format.
Thank you guys so much for your time.
Body.js code:
Template.Body.onCreated(function appBodyOnCreated() {
Meteor.setInterval(() => {
var h = (new Date()).getHours();
const m = ((new Date()).getMinutes() <10?'0':'') + ((new Date()).getMinutes());
var ampm = h >= 12 ? ' PM' : ' AM';
ampmReac.set(ampm);
if (h > 12) {
h -= 12;
} else if (h === 0) {
h = 12;
}
const timeAsAString = `${h}${m}`;
const timeAsAStringFormat = `${h}:${m}`;
whatTimeIsItString.set(timeAsAStringFormat + ampm); // convert to a string
const timeAsANumber = parseInt(timeAsAString); // convert to a number
whatTimeIsIt.set(timeAsANumber); // update our reactive variable
if (Timetables.findOne({TimeStart: whatTimeIsItString.get()}).TimeStart == whatTimeIsItString.get())
{
var nowTimetable = Timetables.findOne({TimeStart: whatTimeIsItString.get() });
Timetables.update({_id : nowTimetable._id },{$set:{isActive : true}});
console.log('I am inside the START statement');
}
else if (Timetables.findOne({TimeEnd: whatTimeIsItString.get()}).TimeEnd == whatTimeIsItString.get())
{
var nowTimetable = Timetables.findOne({TimeEnd: whatTimeIsItString.get() });
Timetables.update({_id : nowTimetable._id },{$set:{isActive : false}});
console.log('I am inside the END statement');
}
}, 1000); //reactivate this function every second
});
})
Very probably it is just that your if / else blocks does what you ask it:
It tries to find a document in Timetables, with specified TimeStart. If so, it makes this document as "active".
If no document is previously found, i.e. there is no timeslot which TimeStart is equal to current time, then it tries to find a document with specified TimeEnd.
But your else if block is executed only if the previous if block does not find anything.
Therefore if you have a next timeslot which starts when your current timeslot ends, your if block gets executed for that next timeslot, but the else if block is never executed to de-activate your current timeslot.
An easy solution would be to transform your else if block in an independent if block, so that it is tested whether the previous one (i.e. TimeStart) finds something or not.
Ok so I got it to work eventually. My problem was that it was never going to the second IF statement.
What I have done is set up a whole new Meteor.interval(() >) function, and placed that second IF in there, as is.
I think the problem was that it was it checks the first IF statement and gets stuck there, no matter what the outcome of the parameters is.

search command ignores special characters

What I'm trying to do: I'm trying to parse Google Calendar events and create a Google Document if the following string is found in the title or description of the event "#notes".
What actually happens: A document is created as soon as the string "notes" is found. It doesn't require an hashtag. The same thing happens with #.
function createMeetingNotesNextTimePeriod() {
//<-------------------------------------VARIABLES
// get today's date
var today = new Date();
// number of hours from now to check for meetings
var hours = 2
// create variable for now
var now = new Date();
// create variable for number of hours from now in milliseconds
var period_from_now = new Date(now.getTime() + (hours * 60 * 60 * 1000));
// retrieve all calendar events for time period with #notes string
var tagword = ('#notes');
var events = CalendarApp.getDefaultCalendar().getEvents(now, period_from_now, {search: tagword}) ;
Logger.log('Number of events: ' + events.length);
} // functionCreateMeetingNotesNextTimePeriod
The log commands tells me that it found one event but the event in question just has 'notes' in it's title, no hashtag. Thanks for all help.
EDIT
I think I found the problem but I'm still stumped about solving it. It seems that the search option from .getEvents ignores most special characters and returns a positive whenever you search for a special character. For example, I replaced my original search for tagword with this:
var events = CalendarApp.getDefaultCalendar().getEvents(now, period_from_now, {search: 'notes' + '#' +'#' + '±' }) ;
It gives me a positive match on my search while I don't have either a '#', a '#' nor a '±' in my event.
That does seem odd that it ignores special characters however here is a work around that should work:
var tagword = '#notes';
var events = CalendarApp.getDefaultCalendar().getEvents(now, period_from_now, {search : tagword})
if (events.length > 0) {
for (i in events) {
if ( events[i].getTitle().indexOf(tagword) >-1 || events[i].getDescription().indexOf(tagword) >-1) {
//do something
}
}
}
Basically it will find all events that have notes (ignoring the special characters) then loop through the event titles and descriptions to check if the tag word is present (including special characters).
You will need to use some Regex to do what you are trying to do in Javascript.
I am not exactly sure how to do it for your particular case but here are two references that can help you out.
JS Extract HashTags From Text
JS Regex Searching for HashTags
I hope this helps !
EDIT
try
var tagword = ('/#/g' + notes);
OR
var tagword = ('/#notes/g');
I tried it out and it seems to have worked.

How to write arguments in function?

I have been using functions but I am not able to tackle this.
What I have done is created a function, then made this to use the values provided by the document class or ids and do the work. Once work is done then just give the data back! It worked!
Now I want to make this function happen for two divs, the first function works good. The issue is with the second one. The function is correct, their is some other bug while writing the result.
Here is my code:
function time_untilCom(id) {
var Time2 = Date.parse(document.getElementById("time_" + 2).value);
var curTime2 = new Date();
var timeToWrite2 = "";
var seconds2 = Math.floor((curTime2 - Time2) / (1000));
if (seconds2 > 0 && seconds2 < 60) {// seconds..
timeToWrite2 = seconds2 + " seconds ago";
$('#update_' + 2).html(seconds2);
$('#jstime_' + 2).html(timeToWrite2 + " <b>Time that was captured!</b>");
}
}
If I use it as it is, it works! The issue comes when I try to replace these
("time_" + 2), ("#update_" + 2), ("#jstime" + 2) with ("time_" + id), ("#update_" + id), ("#jstime_" + id).
What i want to happen is that the function would be provided with a common ID that is applied throughout the div and use that ID, to get the value of time, convert it to seconds, do other stuff and then provide me with the result in the corresponding element with the id that was in the argument.
function works great, it do provide me with the result. But the issue is with the id its not being sent I guess. Or if is being sent then not being applied. What might be the issue here? And don't mind the seconds i have that covered too.
I am really very sorry for short code:
Pardon me, I was about to write the code for the function too. But electricity ran out!
Here is the code: onload="time_untilCom('2'), this is the way I am executing this.
And once in the main code, it will be executed like this: onload="time_untilCom(#row.Id) because I am using ASP.NET Web Pages I will be using the server side code to write the ID from Database. And will then user the ID throughtout the div to update the time!
From what I understand, you probably want to replace the second line
var Time2 = Date.parse(document.getElementById("time_" + 2).value);
with
var Time2 = Date.parse(document.getElementById(id).value);
And at the end you can also use
$('#'+id).html(timeToWrite2 + " <b>Time that was captured!</b>");
You are passing "id" as an argument, but you never use it inside the function. My question is: In your example you are using 2 as appendix to id attributes. Is it the 2 (or other numbers respectively) that you want to have as the id parameter of the function?
Then you could just replace each + 2 in your code by + id
function time_untilCom(id) {
var Time2 = Date.parse(document.getElementById("time_" + id).value);
var curTime2 = new Date();
var timeToWrite2 = "";
var seconds2 = Math.floor((curTime2 - Time2) / (1000));
if (seconds2 > 0 && seconds2 < 60) {// seconds..
timeToWrite2 = seconds2 + " seconds ago";
$('#update_' + id).html(seconds2);
$('#jstime_' + id).html(timeToWrite2 + " <b>Time that was captured!</b>");
}
}
EDIT: Please tell us where and how exactly do you call time_untilCom? Did you pass the id there?

Trouble Displaying Words in Sequence In JQuery and JavaScript

I have been trying to make a simple word sequence display program in jQuery. I want to achieve a simple program that can take sentence as input and its output can be displayed in sequence of words.
Now how can I make this program show these words in sequence like below
<div class="bar">One Two </div> //(hide it after few seconds and show next line)
<div class="bar">Three Four </div> //(hide it after few seconds and show next line)
<div class="bar">Five Six </div> //(hide it after few seconds and show next line)
<div class="bar">Seven </div> //(hide it after few seconds)
The number of words displayed at a time in sequence can be configured using wordCount var in my program
My Program at JSFiddle
I have tried a lot of options on this and its always displaying the last word "Seven" in the div. The animation seems to work right amount of time, that makes me think it has to do with the way JS handles delay in animations.
I guess this goes back to the clear understanding of few things Not sure how JavaScript is handing the delay here.
I have tried following but did not work
- setTimeout - calling the function with a delay
- jQuery.delay() call
When I put the console.log messages it does show me all the words in sequence however the div always contains the last word.
I guess JavaScript is not waiting for the animations to complete and the last word reaches too soon and animation continues later.
I guess the main line of code to look at would be
$('.bar').fadeIn(1000).text(displayWords).fadeOut(1000);
Any help and insight on this would be greatly appreciated.
Try below version using setInterval,
var words = $('.foo').text().split(' ');
var index = 0;
var wordCount = 3;
var showHide = setInterval(function () {
var displayWords = "";
var mx = index + wordCount;
if (mx > words.length) mx = words.length;
for (var i = index; i < mx; i++) {
displayWords += words[i] + " ";
}
$('.bar').fadeIn(1000).text(displayWords).fadeOut(1000);
index = mx;
if (index > words.length) clearInterval(showHide);
}, 2000);
DEMO: http://jsfiddle.net/9T4HE/15/
Have a look at jQuery.queue()...
http://api.jquery.com/queue/
here is the code from the above url:
var div = $("div");
function runIt() {
div.show("slow");
div.animate({left:'+=200'},2000);
div.slideToggle(1000);
div.slideToggle("fast");
div.animate({left:'-=200'},1500);
div.hide("slow");
div.show(1200);
div.slideUp("normal", runIt);
}
function showIt() {
var n = div.queue("fx");
$("span").text( n.length );
setTimeout(showIt, 100);
}
runIt();
showIt();
The runIt() method adds the animations to the queue and the showIt method invokes the queue with a timeout.
The URL above also shows a demo of various animations running in succession.
HTH

Show Div When Dates Match Using .Each

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.

Categories

Resources