Formatting events according to start time - php

Still working on my planner/calendar application. I'm nearly done, I got some of the harder parts working but I'm stuck at one more difficult part. I want to show my events in a grid according to their start time.
It doesn't show in this picture, but pretend there's a column with hours (8am - 11pm or so) at the left of the 25th. If an event starts at.. say, 1pm, I would like it to show somewhere in the middle of the page. If an event starts at 8:30 am, it should show between 8am and 9am.
I guess I could do this with tables, but I was wondering if there's another way. Is this doable with plain html/css, perhaps some Javascript? Any suggestions on what the best way would be to achieve this? If I use a table, I'm still not sure what would be the best way to do this. A cell for every thirty minutes? I have access to the start and end time of each event from my view. An event array (in this example, the 25th) looks like this:
Array
[1] => Array
(
[title] => Ethiek
[description] => Ethiek: Opdracht 1
[time_start] => 11:30:00
[time_end] => 12:00:00
)
[2] => Array
(
[title] => Project Management
[description] => Test: Project Management
[time_start] => 15:00:00
[time_end] => 16:00:00
)
[event_count] => 2
I appreciate any advice you can give me. Thanks a lot!
EDIT: Started a bounty on this because I'm still stuck and I would appreciate some feedback.
UPDATE:
I've been breaking my head over this and I honestly can't figure out the best way to do this. First of all, I think the reason I'm stuck is the way I read out my events from the db/array. This is the code I have to display the events as seen in my screenshot, don't mind my complex arrays:
foreach($details[0] as $key => $detail)
{
echo "<div class='grid'>";
$header = "<p class='detail_header'>";
$header .= ucfirst($dates[0][$key]['name']) . ", " . $key . " " . $init['curr_month_name'];
$header .= "<img src='" . base_url() . "assets/images/create_event.png' alt='Plan iets'></p>";
echo $header;
for($i = 1; $i <= $details[0][$key]['event_count']; $i++)
{
echo "<div class='event " . $details[0][$key][$i]['type'] . "'>";
echo "<p class='event_title'>" . $details[0][$key][$i]['title'] . "</p>";
echo $details[0][$key][$i]['description'];
echo "</div>";
}
echo "</div>";
}
It's a bit of a mess, not to mention that I have the same code another time to fix some exceptions. But more importantly.. I feel like those loops don't allow me to make a lot of modifications to it. I tried adding two divs for AM and PM so I could split up the events in before-noon and afternoon blocks, and then just display the time on the event (to avoid having to work with a thousand blocks of 15 minutes). But yeah.. That didn't work out since it would put a couple of 'PM' divs if there is more than one event in the afternoon.
I'm tempted to just leave it like it is for now and just display the start/end time in the event divs.. until I figure out a better way to read them from the array and display them.
Any help/suggestions appreciated. Thanks.

I'm actually also doing this right now. My solution was to go with 960.gs-like divs.
First, I define a series of constants: Start time to display, end time to display, columns per hour, total columns. In my app's case, these variables are configurable by the user.
Second, I query an array of events that I need to deal with. These include a start time and end time, plus the details I want to display. I'll be using jQuery QTip to popup details that hover, so data to populate those is also included in this query.
Now, the 960.gs concept. The basis for a grid is knowing that you have X amount of space to display your content...with 960, it's 960 pixels. Mine is more custom, but this provides the concept. You can divide this by quite a few numbers, which becomes the basis for how to split the grid. Using this approach, I can easily define a column from grid_1 to grid_4, and it will take a width that is a commensurate percentage of the overall width (i.e. on a 16 column layout doing a 4 column div would cover 25%) It's cross-browser compatible, and doesn't require an overt amount of clear divs. You just need to make the numbers add up to match the amount of columns you want to work with.
Now, I begin by doing the math to figure out how much time each column represents. I assemble each day using a foreach loop: I start with the hour of the display start time and increment up. If the start_time of an event equals the incrementer, I start a div that's styled appropriately based on my coloring criteria. Likewise, if my end time <= the incrementer, I stop the div and define the column's width in the id. Obviously, at the end of the loop, I do an incrementer++. Repeat per day that you display.
My concept is doing this on an time basis for a weekly type calendar. But the overall idea could easily be modified for a month-style calendar or even for a day calendar.
Tables definitely make this easier (version 1 was tables) but it can be done either way if you have the patience.

Your idea about tables sounds like the best option. Assuming that the table borders are all hidden, you can go down to whatever time slot size your application dictates without making it look too messy.
I'd just start with a row representing 15 minutes if they just need to line up roughly at the correct times. Your :hover effect on each block could show the exact times, and the table is then just there to allow you to rowspan your events through rough 15 minute timeslots to make it line up enough that it's visually representative.

You could go with a css approach and absolute positioning of your calendar entries. You would then need a css class for each timeslot. Just to give some orientation:
.timeslot_0 {
position: absolute;
top: 0px;
}
.timeslot_1 {
position: absolute;
top: 50px;
}
.timeslot_2 {
position: absolute;
top: 100px;
}
<div id="calendar">
<div class="day">
<div class="entry timeslot_0>Schedule Enty</div>
<div class="entry timeslot_2>Schedule Enty</div>
</day>
<div class="day">
<div class="entry timeslot_1>Schedule Enty</div>
</day>
<div class="day"></day>
<div class="day"></day>
<div class="day"></day>
</div>
It's the same idea as it is bedind 960grid
As an alternative you could maybe use a percentage for the position from the top so 8am would be 8% and 6pm 100%. It's a bit tricky depending on the available size and stuff but could work out. Haven't tried it yet. Just stuck my mind as another possibility.

I would advise not to use tables, but instead Javascript and CSS.
Use Javascript to get the width of the calendar background: eg: 800 pixels.
Split this width to accommodate 30 minute slots for 24 hours; 800 / (24 * 2) = 16 pixels
24 * 2 (48) is how many 30 minute slots there are in 24 hours.
16 pixels is how much space you have per 30 minutes.
For each event you have, take it's start time in blocks of 30 minutes and multiply it by 16 pixels to get it's position from the left hand side.
For an event that starts at 2:30 (5x 30 minute blocks), 5 * 16 = 80 pixels from the left
For an event that starts at 12:00 (24x 30 minute blocks), 24 * 16 = 384 pixels from the left
For an event that starts at 14:30 (29x 30 minute blocks), 29 * 16 = 464 pixels from the left
I suggest the easiest way to implement this is by using the power of jQuery;
var usableWidth = $('div.calendar').width();
eventsCollection.each(function(singleEvent) {
$(singleEvent).width = (getStartTimeInMinutes(singleEvent) / 30) * (24 * 2);
});
In order to do this, you would need to represent your events in JSON (Javascript Object Notation). Using php, this is easy with json_encode().
This method can be a little complicated to understand at first, but it keeps your markup (HTML) very clean and works really well with any size screen. Most importantly, as your events will be represented as Javascript Objects, it gives you a really great starting point to making a really rich Ajax application.

glad to hear you're making progress.
Tables still appear to me the best solution for this. Think about this:
- you can style width, height, etc, to set them in a grid like way, which is what you want.
- you know exactly the structure, so running through the table is simple loop code
And the clincher for me:
- tables provide accessibility. Because screenreaders have ways to interpret tables in meaningful ways for sight-impaired viewers, the tables a particularly helpful when the contents is made meaningful by the rows and columns, which is exactly what you've got.
By the way, put in the URL of a running version for us when you're done.

Yo. I have been looking at a similar problem for a calendar module of a website I have to build. I am putting it together in c# so the code would not really suite your answer full but the way that i've looked at data may help.
Now tables are pretty hard so forgive the crudness of this :P
-------------------------------------------------------------------------------------------
hrs | mins |total mins|
day start time | 10 | 0 |600 |running time in mins
day end time | 23 | 30 |1410 |810
item start time| 13 | 0 |780 |running time | distance to cover | starting point
item end time | 16 | 40 |1000 |220 | 27.16% | 180
-------------------------------------------------------------------------------------------
If you will look at the above. I have a day with start time or end time. This can be converted to what ever time format you need week month whatever. The point is that you can look at all your items and find the earliest start date and latest end time calculating 100% of your event distance(for me 810 mins).
From here you can calculate % points that an individual even needs to cover
(single event run time/total event runtime * 100). This would be the distance to draw that individual item.
And give that item a starting point(this should be a percentange as well) but starting point for event one is 180 mins(total event start time - item event start time )
Thanks.
KJ

Related

Convert mysql irregular time series data to regular sequence

I have a table of temperature data, updated every 5-15 mins by multiple sensors.
The data is essentially this: unique id, device(sensor id), timestamp, value(float)
The sensors does not have an accurate clock, so the readings are doomed to skew over time, so I'm unable to use things like group by hour in mysql to get a reading of the last 24h of temperature data.
My solution as a php programmer would be to make a pre-processor that reads all the un-processed readings and "join them" in a table.
There must be others than me who has this need to "downscale" x-minute/hour reads down to one per hour, to use in lets say graphing.
My problem is how do I calculate the rounded hour value from one or several readings.
For example, I have 12 readings over 2,5 hours, and I need an explicit value for each whole hour for all these readings.
Data:
Date Device Value
2016-06-27 12:15:15, TA, 23.5
2016-06-27 12:30:19, TA, 23.1
2016-06-27 12:45:35, TA, 22.9
2016-06-27 13:00:55, TA, 22.5
2016-06-27 13:05:15, TA, 22.8
2016-06-27 13:35:35, TA, 23.2
I'm not that much into statistical math, so "standard deviation" and the likes are citys in Russia for me.
Also, the devices go to sleep sometimes, and does not always transmit a temperature.
Feel free to ask me to add info to the question, as I'm not sure what you guys need to answer this.
The most important parts is this:
1. I'm using MySQL, and that's not going to change.
2. I'm hoping for a solution (or tips) in php, though tips in many other languages also would help my understanding. I'm primarily a PHP programmer though, so answers in that language would be most appreciated.
Edit: I would like to specify a few points.
Because the time data recorded from the sensors may be inaccurate, I'm relying on the SQL insert time. That way the time is controlled by one device only, the controller that's inserting the data.
For example, if I select 30 timestamp/value pairs in a 24h period, I would like to "combine" these to 24 timestamp/value pairs, using an average to combine the overflowing data.
I'm not that good to explain, but I hope this makes it clearer.
Also, would love either a clean SQL way of doing it, but also a PHP way of looping through 30 rows to produce 24 whole hour rows of data.
My goal is to have one row for every hour, with an accurate timestamp and temperature value. Mainly because most graphing libraries expect that kind of input. Especially when I have more than one series in a graph.
At some point, I may find it useful to show a graph for let's say the last six hours, with a 15 minute accuracy.
The clue is that I don't want to change the raw data, just find a way to extract/compute linear results from it.
How I would try to handle this is;
Take day start value; 01/01/2016 00:00:00 and do a 'between' 'sql' in MySQL, progressing every hour. So the first 'sql' would be like;
'select avg(temp_value) from table where date between 01/01/2016 00:00:00 and 01/01/2016 00:59:99' and progress on by the hour.
The sql isn't correct, and the entire 24hr period can be written out programmatically, but I think this will start you on your way.

clever way to increment a value in a large array

Hep hey!
I am building an statistic overview of how many people is supposed to be at work at any given 5 minuts interval on a given day.
Say, we have 6 people working at 10.50, same at 10.55, then one go home and we got 5 people working at 11.00
Now, the way i imagined to keep track of this was to have an array with 5x12x24 elements (1 element per 5 minuts for an 24 hour interval), where i run through each employees shift time and increment the elements for the given 5 min intervals their shift takes them over.
(say a person works from 9.00 to 10.00, then i will increment the values from 9.00, 9.05, 9.10 up to 10.00 by one)
I need the data to make a diagram later, that is why i store it in an array.
Now my question is, which way is the fastest to do this?
Should i start out with an array which contains all the time elements and then increment it as i run through the shift hours of the employees ($arr['9.05']++) or should i start out by making an empty array and just check if the value of the time exsists, if not, create that element and if it does, increment it?
Or is there in general a smarter way to do this?
I ask as i can see this becomming a pretty heavy operation if you have 50+ employees which have to run through this function, so the smarter it can be made, the better :)
PS. the shift times comes from a database that i do not have access to, so i only have the timestamps of the start of the shit and the finish.

Can text be inserted into a fusion chart?

I'm using the Grid component in fusion charts and need a date string to be used in the value place. It will always fail when i do this as it is looking for a number. Is there anyway it can allow text to be used aswell?
Thanks
The ability to have date-time axis values is not yet available in FusionCharts. Nevertheless, the use case for you does not fit right.
Ideally, the grid component's right column should show a number (value). The left column is text showing the labels. For a grid, it makes very less sense to have text on both columns.
Instead of a date, the right column should show how many month's or days or hours, etc.
Excerpts from FusionCharts documentation: http://docs.fusioncharts.com/charts/contents/advanced/number-format/Number_Scaling.html
Say we're plotting a chart which indicates the time taken by a list of automated processes. Each process in the list can take time ranging from a few seconds to few days. And we've the data for each process in seconds itself. Now, if we were to show all the data on the chart in seconds only, it won't appear too legible. What we can do is build a scale indicating time and then specify it to the chart. This scale, in human terms, would look something as under:
60 seconds = 1 minute
60 minute = 1 hr
24 hrs = 1 day
7 days = 1 week
Now, to convert this scale into FusionCharts XML format, you'll have to do it as under:
First you would need to define the unit of the data which you're providing. Like, in this example, you're providing all data in seconds. So, default number scale would be represented in seconds. We can represent it as <chart defaultNumberScale='s' ...>
Next, we define our own scale for the chart as: <chart numberScaleValue='60,60,24,7' numberScaleUnit='min,hr,day,wk' >. If you carefully see this and match it with our range, you'll find that whatever numeric figures are present on the left hand side of the range is put in numberScaleValue and whatever units are present on the right side of the scale has been put under numberScaleUnit - all separated by commas.
Set the chart formatting flags to on as: <chart formatNumber='1' formatNumberScale='1' ...>
The entire XML would look like:
<chart defaultNumberScale='s' numberScaleValue='60,60,24,7' numberScaleUnit='min,hr,day,wk'><set label='A' value='38' /><set label='B' value='150' /><set label='C' value='11050' /><set label='D' value='334345' /><set label='E' value='1334345' /></chart>
A sample grid (not with the above data) would look like this:

How would you make this simple scheduler?

I'm working on an admin section right now to schedule employees for their shifts. It is simple in that on any day, employees work either the day or the night shift. How would you go about doing this so that it is easy to display? I was thinking I have a table with the employee names going down the first column. Then, the next 7 columns are the upcoming 7 days. Each cell would be a drop down with Not Scheduled, Day Shift and Night Shift as the three choices. Is this how you'd do it? I've never done anything like this so I could really use some advice.
Thanks!
For something like employees you're probably going to see a lot of text no matter what. Why not just list in times and out times, sorted by time?
John Smith in 7:30
Mary Anne in 7:30
John Smith out 4:00
Mary Anne out 4:00
You could color-code in vs out. You could also break it down to 5 10 15 or 30 minute increments for sections, though i'm not sure what the value would be. Maybe faster visual reference?
Do something like this for a "day" view which can be drilled in from week/month, etc. While you're at it you could easily create an employee schedule view that could be a little bit more graphical.
Edit:
I suppose the above doesn't address your question so much as it exemplifies what you can do with the data once you have it.
For scheduling you could create a pretty basic form comprised of a sort of lookup/autocomplete field for the employee name, and a date field and 2 time fields (in/out). If you use something like jQuery dialog, you could insert these schedules directly from any other schedule view to help you see what you're looking for. You could pretty easily fit 7 columns wide of lists of in and out times to represent a week in sort of a "spread" view. You could have options to page by week or by day. In paging by day you would have sort of a rotation capability, which might be handy if the end of one week can impact the beginning of the next.
I think, as the admin, I could prefer something just a bit simpler. A drop-down with Day or Night; and the ability to choose neither, if no shift.

PHP AJAX mysql event calendar - UI for events spanning multiple days

I have built a PHP calendar system and have pretty much everything done but not sure how to deal with a UI issue involving how the events that stretched out over a couple of days. I want to be able to stretch an event that stretches over couple of days in a div that spans those days in the calendar. Basically I would like to know how to achieve what these guys have achieved with the event that stretches out from 21st to 22nd with the yellow div background.
I have been trying to see how I can do it with PHP but I feel like I might be trying the wrong thing. Perhaps this is done with javascript?
Really, to explain how to do this would take quite a while. I can give you some general pointers, however...
Basically, in the example you provided, the authors of that calendar used absolutely-positioned divs that layed over the calendar. If you open up Firebug in Firefox and 'inspect element' one of the spans, and then watch the element as you re-size the browser, you'll notice that they turn yellow. This is because JavaScript is actively re-sizing the elements when items are added or when the page is re-sized. I tried to do something similar to this for a while and eventually gave up due to it's complexity and unnecessary cumbersomeness.
What I eventually did was go against my strong anti-table mentality and used the colspan attribute of <td> elements in the table itself. Each line of events is a <tr> and each event is a <td>. Since <td>s can span multiple "columns" using the colspan attribute.
So, to break it down...
The calendar is a <div>. Each week is another 100%-width <div> that contains two tables:
The first table just contains the cell borders, to give the calendar look.
The second contains the the day numbers, events, etc...
In the second table, the first row has 7 columns (1 for each day of the week). All the tertiary rows only have the number of rows necessary to show their events. So, a week that only has 1 event, on, say, Thursday which spans 2 days (from Thurs. to Fri.) would have 6 columns:
That row would be something like:
<tr>
<td class="no-event"></td> <!-- Sunday -->
<td class="no-event"></td> <!-- Monday -->
<td class="no-event"></td> <!-- Tuesday -->
<td class="no-event"></td> <!-- Wednesday -->
<td class="no-event" colspan="2"> <!-- Thursday through Friday -->
<div class="some-styling-class">Vacation to Orlando!</div>
</td>
<td class="no-event"></td> <!-- Saturday -->
</tr>
Notice how there are only 6 columns... (since the event with colspan="2" takes up 2 columns worth).
Each table is positioned fixedly to the parent 'week' div... the first one has a lower z-index so that the second table (events, etc...) will show up on top and span over the calendar cell borders.
This is actually what Google uses to construct their Google Calendars. It's actually quite elegant, easy to work with, and there's little-to-no crazy javascript to write. The most challenging thing is to wrap an event from, say, Thursday on one week to, say, Wednesday on another week (since you have to make n number of colspans <td>'s depending on the amount of weeks spanned in the visible calendar space).
So, my suggestion would actually be to investigate Google's G-Cal table structure and see what you can extrapolate from that. The easy way is to just copy the entire HTML from it using Firebug and paste it into an editor and then just toy around until you understand how it works.
I hope what I've shown helps. Good luck dude.
The way Google Calendar solves this problem is, believe it or not, through tables. It's a bit more sophisticated (they have one table for the calendar grid, and then superposed on top is another table for the events inside), but the basic approach will have you use multiple rows for each calendar box, and put one event per row, per column. Then when you want to stretch the event over multiple days, you simply use colspan on the table cell for that specific event. Something like this:
===============================
|| Monday || Tuesday ||
===============================
|| Evt 1 || Evt 2 || ...
-------------------------------
|| Evt 3 (colspan=2) ||
-------------------------------
|| || ||
------------------------------- ...
|| || ||
===============================
|| Monday || Tuesday ||
===============================
...
Where the double lines represent borders that you actually render, and the single lines represent invisible borders between rows. In this example, you'd have 4 rows per calendar grid (so you can have a maximum of 4 events in a day).
You can achieve all this from PHP through careful rendering of the HTML and use of CSS.
Something else I would recommend is like Michael said, study Google Calendar, but a much better way than looking at the code would be to get Firefox (you hopefully have it already) and install the extension Firebug (that you also hopefully already have). Then go to the Firebug menu and choose "Inspect element" and click on one of the events on the calendar, and study the structure from there on.
The problem with using a single div spanning multiple 'cells', is that you'll be confronted with line breaks. Say, an event lasts from thursday until tuesday, but each week (starting at monday) will get its own row.
An alternative solution would be to use multiple divs, and setting a seperate class for the first and last days of an event. Something like...
<div class="event01 first">(text)</div>
<div class="event01"></div> <!-- repeat -->
<div class="event01 last"></div>
Ofcourse, the downside to this would be that the description will be limited to the first div. Hence, a combination of two would probably work best; one div spanning from the start to the end of the week, and a second (and possibly third one, etc) until the end date of the event.
Or, in the case of tables, you could ofcourse combine Tekahera's answer:
<td class="event01 first last">1-day event</td>
<td class="event01 first">Multi-day event</td>
<td class="event01"></td>
<td class="event01 last"></td>
In both examples, the "event01" class will set the background and top/bottom borders, while the "first" and "last" classes would set the left and right border, respectively. (By default, these will be 0).

Categories