event year view in fullcalendar v4 - javascript

I would like to display year view of events in fullcalendar v4. Year view has been added to full calendar until version 2.2.7. Later version does not have this. So, I decided to create year view using custom view . But I did not get where should I add the html part that display year view in the way we want. This is how I create a view. But listYear plugin able to display all events in the year in list form. I would like to display events in calendar display all month on one view. Is it possible to add our own html table to render in calendar?
views: {
Year: {
type : 'listYear',
duration : {
months: 12
},
start :year+'-01-01',
end :(year+1)+'-01-01',
buttonText:'year'
}
}
document.addEventListener('DOMContentLoaded', function() {
var year =<?php echo $year;?>;
var event ='<?php echo json_encode($events);?>';
event=JSON.parse(event);
//console.log(event);
//create event Array
events_array=[];
for(i=0;i<event.length;i++)
{
//parameter for event Array-https://fullcalendar.io/docs/event-object
start_array=event[i]['start'].split(" ");
end_array=event[i]['end'].split(" ");
if(start_array[1]==='00:00:00')
{
start =start_array[0];
}
else
{
start =event[i]['start'];
}
if(end_array[1]==='00:00:00')
{
end =end_array[0];
}
else
{
end =event[i]['end'];
}
object_data={
id :event[i]['id'],
title :event[i]['remark']+'-'+event[i]['title'],
start :start,
end :end,
color :event[i]['color'],
}
events_array.push(object_data);
}
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
plugins: ['dayGrid','list'],
header:
{
left : 'prev,next today',
center : 'title',
//version 2.2.7 able to show year view.Year view has been implemented until version 2.2.7.
//But , we are using 4 to use valid range (limiting the duration).Valid range available from 3.3.0
right : 'Year,dayGridMonth,dayGridWeek,dayGridDay,listMonth'
},
views: {
Year: {
/* type: 'timelineYear',*/
type: 'listYear',
duration: { months: 12
/*weeks:1*/ },
start:year+'-01-01',
end: (year+1)+'-01-01',
/*intervalStart: $.fullCalendar.moment(year+'-01-01'),
intervalEnd: $.fullCalendar.moment((year+1)+'-01-01'),*/
buttonText: 'year'
}
},
defaultDate: year+'-01-01',
//set the year range limit - fullcalendar.min.js v3.3.0 & above support this
validRange: {
start : year+'-01-01',
end : (year+1)+'-01-01'
},
defaultView : 'dayGridMonth',
editable : false,//disable drag
events : events_array,
//from [https://stackoverflow.com/questions/45698134/dayrender-not-properly-working-in-fullcalendar-on-given-dates]
dayRender: function (date, cell)
{
var disabledDates = ["2016-02-10", "2016-02-15"];
//$.inArray returns the index of the element in the array, not a boolean indicating if the item exists in the array. If the element was not found, -1 will be returned.
/*if ($.inArray(date.format("YYYY-MM-DD"), disabledDates) > -1)
{
cell.css("background-color", "green");
}
*/
}
});
calendar.render();
});
Thanks in advance

My aim is to use version 3 and above since it support the valid range function and version 3 custom view is quite understandable. So, I had use version 3 to do year view. This year view limited for only one year that consist of 12 months. Declare custom view in fullcalendar instantiation.
views:
{
CustomView:
{
type: 'custom',
}
}
Declare a button year in header for custom year view . Then in customButtons:, define what happen when user click this button.
customButtons:
{
year:
{
text:'year',
click: function()
{
$('#calendar').fullCalendar('changeView', 'CustomView');
}
}
}
Then, get reference(FC) to fullcalendar's root namespace and class(View) that all views inherit from.
var FC =$.fullCalendar;
var View =FC.View;
Build the view inside render: function() of our class CustomView. Create table containing 12 field (3 columns and 4 rows) and append to fc-view. Then ,arrange each event in object with required informations and add to events_array.events_array contain objects of events. Get next 12 months start from which period month start in array months. Then, loop in months array and instantiate fullcalendar view in each field in that table created by using the id. Id is value from months(ex:'january_2019'). Set the duration one month and pass in the events array. So, each field show the view for one month together with the events. 12 fields shows view for 12 months.
CustomView = View.extend(
{
render: function()
{ }}
Register our class with the view system.
FC.views.custom = CustomView;
<?php
require_once('bdd.php');
// information from sql
// $event_2 is events array
// $event_3 are array of earliest event start and latest event end date, chosen period start and end date,
?>
<html>
<head>
<style>
#container
{
width: 100%;
position: relative;
}
#calendar
{
width: 900px; /*can be in percentage also.*/
height: auto;
margin: 0 auto;
padding: 10px;
position: relative;
}
td.fc-sun
{
background-color: #535450 !important;
}
</style>
<script src="js/jquery.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src='js/moment.min.js'></script>
<script src='v_3/fullcalendar.min.js'></script>
<link rel="stylesheet" href="v_3/fullcalendar.min.css" />
<script>
$(document).ready(function()
{
var event ='<?php echo json_encode($events_2);?>';
event =JSON.parse(event);
limit ='<?php echo json_encode($events_3);?>';
limit =JSON.parse(limit);
events_array=[];
for(i=0;i<event.length;i++)
{
//parameter for event Array-https://fullcalendar.io/docs/event-object
start_array=event[i]['start'].split(" ");
end_array=event[i]['end'].split(" ");
if(start_array[1]==='00:00:00')
{
start =start_array[0];
}
else
{
start =event[i]['start'];
}
if(end_array[1]==='00:00:00')
{
end =end_array[0];
}
else
{
end =event[i]['end'];
}
console.log(start+'=>'+end);
object_data=
{
id :event[i]['id'],
title :event[i]['remark']+'-'+event[i]['title'],
start :start,
end :end,
color :event[i]['color'],
}
events_array.push(object_data);
}
$('#calendar').fullCalendar
({
defaultDate: limit[0]['earliest'],
validRange: {
start : limit[0]['earliest'],
end : limit[0]['final']
},
header :
{
left :'prev,next,today',
center :'title',
right :'year,agendaWeek,month'
},
events : events_array,
customButtons:
{
year:
{
text:'year',
click: function()
{
$('#calendar').fullCalendar('changeView', 'CustomView');
}
}
},
views:
{
CustomView:
{
type: 'custom',
}
}
})
var view = $('#calendar').fullCalendar('getView');
//custom view:
var FC = $.fullCalendar; //a reference to FullCalendar's root namespace
var View =FC.View; //the class that all views must inherit from
var CustomView; //our subclass
start_year =limit[0]['earliest'].split("-")[0];
end_year =limit[0]['final'].split("-")[0];
start_month =parseInt(limit[0]['fye_start'].split("-")[1]);
CustomView = View.extend(
{
render: function()
{
$('.fc-prev-button').addClass('fc-state-disabled');
$('.fc-next-button').addClass('fc-state-disabled');
//change the title
document.getElementsByClassName("fc-center")[0].getElementsByTagName('h2')[0].innerHTML = start_year;
//https://stackoverflow.com/questions/10832179/result-of-getting-next-12-months-in-javascript-is-messed-up
var months =getNext12MonthNamesWithYear(limit[0]['fye_start']);
var table ='<table align="center" style="width:100%">';
var m=0;
for(i=1;i<=4;i++)
{
table+='<tr>';
for(j=1;j<=3;j++)
{
table+='<td height="100"><div id="'+months[m]+'"></div></td>';
m++;
}
table+='</tr>';
}
table+='</table>';
$('.fc-view').append(table);
for(n=0;n<months.length;n++)
{
year =months[n].split("_")[1];
month=months[n].split("_")[0];
//https://stackoverflow.com/questions/13566552/easiest-way-to-convert-month-name-to-month-number-in-js-jan-01/27805696
month=getMonthFromString(month);//convert month string to month no
//month compulsory to have 2 digit
if(month>=10)
{
c=month;
}
else
{
c='0'+month;
}
$('#'+months[n]).fullCalendar
(
{
header:
{
left: '',
center: 'title',
right: ''
},
events : events_array,
defaultDate : year+'-'+(c)+'-01',
//set the year range limit - fullcalendar.min.js v3.3.1 & above support this
defaultView:'month',
duration:
{
months: 1
}
})
}
},
}
)
FC.views.custom = CustomView; // register our class with the view system*/
})
function getNext12MonthNamesWithYear(date)
{
var now = new Date(date);
var month = now.getMonth();
var year = now.getFullYear();
var names = ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'];
var res = [];
for (var i = 0; i < 12; ++i)
{
res.push(names[month] + '_' + year);
if (++month === 12)
{
month = 0;
++year;
}
}
return res;
}
function getMonthFromString(mon)
{
return new Date(Date.parse(mon +" 1, 2012")).getMonth()+1
}
</script>
</head>
<body>
<div id='calendar'></div>
</body>
Looking forward for better solution.

Related

JavaScript: Fullcalendar - Insert Break / Empty Row Between Months

I'm using Fullcalendar to render a calendar.
Everything is working fine, but I have a specific request that I've been trying to solve, which is: show two months, but have some kind of visual separation (i.e. empty row) between them.
I have my custom view set-up, but have no idea where to even begin on inserting a row between months. (My initial thoughts are: it's probably easier to insert a 'row' into the calendar after it renders, as opposed to getting too deep).
I was thinking about looping through the calendar's HTML on the fc-day-top CSS class and use Moment.js to match the date and then break the row by inserting html into the DOM; but I'm not sure if that's the right approach. (please see the code below and fiddle)
I am able to select the last day of the respective month, but am now trying to figure out the best way to insert HTML into the table with correct offsets before and after the split.
Any help would be much appreciated!
var calendarEl = document.getElementById('my-calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
plugins: [ 'interaction', 'dayGrid','timeGrid', 'list' ],
header: {
left: 'prev,next today',
center: 'title',
right: 'listDay,dayGridMonth,monthView2'
},
views: {
monthView2: {
type: 'dayGrid',
duration: {
months: 2
},
buttonText: '2-Month View',
showNonCurrentDates: false,
},
dayGridMonth: {
buttonText: 'Month View',
showNonCurrentDates: false,
},
listDay: { buttonText: 'Day List' },
},
defaultView: 'monthView2',
// With the code below: my initial though is: find the last day of the month, and insert <td>s and a row to split it
datesRender: function( info ){
$('.fc-row.fc-week').each(function() {
var thisWeek = $(this);
var $d_i = 0;
var htmlCellStringBefore = htmlCellStringAfter = '';
$(thisWeek).find('.fc-day-top').each(function() {
$d_i++;
var thisDay = $(this).data('date');
var thisDateYear = moment(thisDay).year();
var thisDateMonth = moment(thisDay).month();
var lastDay = new Date(thisDateYear, thisDateMonth + 1, 0);
var lastDayMoment = moment(lastDay).format('YYYY-MM-DD');
// Match the last day, if matches, cut the table and insert HTML
if(thisDay == lastDayMoment){
var cellIteratorBefore = 7 - $d_i;
var cellIteratorAfter = 7 - cellIteratorBefore;
// Looping to create number of offset cells before break for insertion
for (i = 0; i < cellIteratorBefore; i++) {
htmlCellStringBefore += '<td class="cellBefore"></td>';
}
// Looping to create number of offset cells after break for insertion
for (i = 0; i < cellIteratorAfter; i++) {
htmlCellStringAfter+= '<td class="cellAfter"></td>';
}
var returnHtmlHead = htmlCellStringBefore + '</tr></thead>'; // inserting empty cells after date to break into head
var returnHtmlBody = htmlCellStringBefore + '</tr></tbody></table>'; // inserting empty cells after date to break into table body
var thisTableFcBG = $(thisWeek).find('.fc-bg tbody td');
var thisTableFcSkeleton = $(thisWeek).find('.fc-content-skeleton tbody td');
var thisTableFcBGNthTableCell = $(thisTableFcBG)[cellIteratorBefore];
var thisTableFcSkeletonNthTableCell = $(thisTableFcSkeleton)[cellIteratorBefore];
var MonthName = moment(lastDayMoment).add(1, 'days').format("MMMM");
$('<div class="break-month-title">'+ MonthName+ '</div>').insertAfter(thisWeek);
// This part is messy and i'm trying figure out the best way to split up the tables
$(returnHtmlHead).insertAfter(thisDay);
$(returnHtmlBody + '<div class="fc-row fc-week fc-widget-content"><div class="break-month">BREAK MONTH</div><div class="fc-bg"><table><thead><tr>'+ htmlCellStringAfter).insertAfter(thisTableFcBGNthTableCell);
$(returnHtmlBody + '<div class="fc-content-skeleton"><table><thead><tr>' + htmlCellStringAfter).insertAfter(thisTableFcSkeletonNthTableCell);
}
});
});
}
});
calendar.render();
.break-month {
background:#f10000;
}
.break-month-title {
text-align:center;
padding:3rem;
font-size:2rem;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/core/main.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://momentjs.com/downloads/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/core/main.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/interaction/main.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/daygrid/main.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/timegrid/main.min.js"></script>
<div id="my-calendar"></div>
I also have a fiddle: https://jsfiddle.net/zjr73m41/

How can I build a dataTable, with a dropbox filter on top, calculated on backend?

I need to change a dataTable to add a dropbox on top of it (not in the header) to filter it.
I have this column with dates like dd/mm/yyyy and I the year range does not go from 01/01/N to 31/12/N. It goes from 01/11/N to 31/10/N+1 and this rule will be used to calculate the filters available.
In case I have only this to lines :
-------------------------------------------------------
| date_header | header 2 | header 3 | header 4 |
|-------------------------------------------------------|
| 01/05/2013 | abc | qwe | xyz |
|-------------------------------------------------------|
| 05/11/2018 | hdf | ydb | lot |
-------------------------------------------------------
I should get the following results on de dropbox (respecting the rule I talked about) :
<2012/2013>
and
<2018/2019>
So, firstly, I need this dropbox to read every values presents on this column and calculate the filter values.
And then, filter the table using the range selected.
-- EDIT1 --
This is my initilialization script:
$element.DataTable({
"ajax": {
"url": this._tableDatasource,
"dataSrc": ""
},
"sDom": 'ltipr',
"bLengthChange": false,
"paging": this._detautNombreElementsPerPage > 0,
"pagingType": "full_numbers",
"iDisplayLength": this._detautNombreElementsPerPage,
"order": [[ this._defautColumnTrie, this._defautTypeTrie ]],
"columns": this._columns,
"columnDefs" : this._columnsProperties,
"fnRowCallback": function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
if ($(nRow).hasClass('even')) {
$(nRow).addClass("alt");
} else {
if ($(nRow).hasClass('alt')) {
$(nRow).removeClass("alt");
}
}
},
"fnDrawCallback": function() {
var pageCount = Math.ceil((this.fnSettings().fnRecordsDisplay()) / this.fnSettings()._iDisplayLength);
if (pageCount > 1) {
$('.dataTables_paginate').show();
} else {
$('.dataTables_paginate').hide();
}
},
"language": {
"sProcessing": "Chargement en cours...",
"sLengthMenu": "Montrer _MENU_ registres",
"sZeroRecords": "Aucun résultat n'a été trouvé",
"sEmptyTable": "Aucune donnée disponible pour ce tableau",
"sInfo": "_TOTAL_ éléments trouvés, affichage de _START_ à _END_",
"sInfoEmpty": "0 éléments trouvés, affichage de 0 à 0",
"sInfoFiltered": "(filtré au total de _MAX_ registres)",
"sInfoPostFix": "",
"sSearch": "Chercher:",
"sUrl": "",
"sInfoThousands": ",",
"sLoadingRecords": "Chargement en cours...",
"oPaginate": {
"sFirst": "Première page",
"sLast": "Dernière page",
"sNext": "Page suivante",
"sPrevious": "Page précédente"
}
},
"initComplete": function() {
if ($(this).attr('id') == "tableIndisponibilitesPassees") {
var dates = $('#tableIndisponibilitesPassees tr td:first-child').toArray();
populate_dropdown(dates);
//$('#tableIndisponibilitesPassees').dataTable().fnClearTable();
//$('#tableIndisponibilitesPassees').dataTable().fnFilter("20/10/2015 08:00:00").draw();
set_handler();
}
}
});
I had to add the initComplete to populate the table.
This is my populate dropdown :
function populate_dropdown(dates) {
// make an empty array variable to hold the list of saisons
var saisons = [];
// loop through the dates
for (var i = 0; i < dates.length; i++) {
var year = Number($(dates[i]).html().split(' ')[0].split('/')[2]);
var month = Number($(dates[i]).html().split(' ')[0].split('/')[1] - 1);
var day = Number($(dates[i]).html().split(' ')[0].split('/')[0]);
var datePFHA = new Date(year, month, day);
var dateDebutSaison = new Date(year, 10, 1);
// now let's calculate the season
var saison;
if (datePFHA < dateDebutSaison) {
saison = Number(year-1) + "/" + year;
} else {
saison = year + "/" + Number(year+1);
}
// now let's add that saison to the seasons array (if it's not already in the array!)
if ($.inArray(saison, saisons) == -1) {
saisons.push(saison);
}
}
// now that we're done looping through and building the seasons list, let's sort the array
saisons.sort();
// make a variable to hold all the <option> fields for the select dropdown
var options = "";
// loop through the years and make the options fields
$.each(saisons, function(key,value) {
options += "<option> Saison " + value + "</option>";
});
// take the new options string that we've built and put it inside the <select> dropdown
$('#filtre_saison').append(options);
}
And now I'm trying to set the handler like this :
function set_handler(dataTable) {
console.log("set_handler");
var filtre = $('#filtre_saison').on('change', function() {
// when someone changes the filter, get the beginning and ending of the season
var yearsSaison = $("#filtre_saison").val().split(' ')[1];
var debutSaison = new Date(yearsSaison.split('/')[0],10,01);
var finSaison = new Date(debutSaison.getFullYear() + 1, debutSaison.getMonth(), debutSaison.getDate());
console.log($('#tableIndisponibilitesPassees'));
console.log($('#tableIndisponibilitesPassees').dataTable());
console.log($('#tableIndisponibilitesPassees').dataTable().fnFilter("20/10/2015 08:00:00"));
console.log($('#tableIndisponibilitesPassees').dataTable().fnFilter("20/10/2015 08:00:00").draw());
$('#tableIndisponibilitesPassees').dataTable().fnFilter("20/10/2015 08:00:00").draw();
//$(dataTable).search("20/10/2015 08:00:00").draw();
//filter_table(debutSaison, finSaison);
});
}
I've tryed the search method on dataTable but it doesn't work. Return an error saying that search is not a function.
I've tryed with the fnFilter but now it returns an error in the draw function saying :
Cannot read property 'draw' of undefined
I've checked and after the fnFilter function, is returning undefined.
--- EDIT 2 ---
Almost forgot. This is my html code :
<select name="filtre_saison" id="filtre_saison">
</select>
Appreciate your help
OK, without any specifics of how the table is built, etc., a general way to go about this might be to use javascript/jQuery to loop through the date fields and build the year list. Then from that year list, you can populate a dropdown. Then you add a change handler to the dropdown and use javascript to show/hide elements based on the selected year.
Here's a quick and dirty example, which is assuming a couple things:
The fields that hold the date has a class (in my case, 'date_element')
The dates in the fields are of a consistent format
You can run the working snippet below to see it in action. And I added lots of code comments to explain what certain lines are doing.
Hope it helps! (and I hope I didn't just do your homework for you...).
// trigger the function that populates the dropdown when the page has finished loading, and then add a change handler on the dropdown
$(document).ready(function() {
populate_dropdown();
set_handler();
});
function populate_dropdown() {
// make an empty array variable to hold the list of years
var years = [];
// loop through the date_header fields (assuming that the elements have a class of date_element)
$('.date_element').each(function(){
// $(this) inside the each function refers to the <td class='date_element'> element
var this_date = $(this).html();
// get the year from the date. It would be better to use actual Date functions, but if the
// dates are consistent, we can just break them apart on the / characters and grab the last value
var this_year = Number(this_date.split('/')[2]);
// now let's add that year to the years array (if it's not already in the array!)
if ($.inArray(this_year, years) == -1) {
years.push(this_year)
}
});
// now that we're done looping through and building the year list, let's sort the array
years.sort();
// make a variable to hold all the <option> fields for the select dropdown
var options = "";
// loop through the years and make the options fields
$.each(years, function(key,value) {
options += "<option>" + value + "/" + Number(value+1) + "</option>";
});
// take the new options string that we've built and put it inside the <select> dropdown
$('#year_filter').append(options)
}
function set_handler() {
$('#year_filter').change(function() {
// when someone changes the filter, get the value of the first year
var selected_year = $("#year_filter").val().split('/')[0];
// make sure it's a number
if (!isNaN(selected_year)) {
filter_table(selected_year);
} else {
show_all_rows();
}
});
}
function filter_table(selected_year) {
//loop through the table rows, show ones that have the year and hide ones that don't have it
$('.date_element').each(function() {
if ($(this).html().indexOf(selected_year) == -1) {
//this row doesn't contain that year, let's hide the whole <tr>
$(this).parent().hide();
} else {
$(this).parent().show()
}
});
}
function show_all_rows() {
$('.date_element').each(function() {
$(this).parent().show();
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<form>
<select id="year_filter" name="year_filter"><option>Filter By Year</option></select>
</form>
<table>
<tr>
<th>date_header</th>
<th>header 1</th>
<th>header 2</th>
<th>header 3</th>
</tr>
<tr>
<td class='date_element'>01/05/2013</td>
<td>abc</td>
<td>qwe</td>
<td>xyz</td>
</tr>
<tr>
<td class='date_element'>05/11/2018</td>
<td>hdf</td>
<td>ydb</td>
<td>lot</td>
</tr>
</table>
Found the solution :
HTML :
<select name="filtre_saison" id="filtre_saison">
</select>
<table>
...
</table>
Javascript code :
"initComplete": function() {
if ($(this).attr('id') == "tableBuildings") {
var dates = $('#tableBuildings tr td:first-child').toArray();
populate_dropdown(dates);
$.fn.dataTable.ext.search.push( function( settings, data, dataIndex, rowData, counter ) {
if (settings.nTable.id === 'tableBuildings') {
//Calculation of beggining and ending of the room
var yearsBuildig = $("#filtre_saison").val().split(' ')[1];
var initialDate = new Date(yearsBuildig.split('/')[0],10,01);
var endDate = new Date(initialDate.getFullYear() + 1, initialDate.getMonth(), initialDate.getDate());
//Calculation of the Date object of the PFHA
var year = Number(rowData.initialDate.display.split(' ')[0].split('/')[2]);
var month = Number(rowData.initialDate.display.split(' ')[0].split('/')[1] - 1);
var day = Number(rowData.initialDate.display.split(' ')[0].split('/')[0]);
var hours = Number(rowData.initialDate.display.split(' ')[1].split(':')[2]);
var buildingDate = new Date(year, month, day);
if (buildingDate >= initialDate && buildingDate < endDate) {
return true;
} else {
//this row doesn't contain that year, let's hide the whole <tr>
return false;
}
} else {
return true;
}
});
$('#filtre_saison').on('change', function() {
table.draw();
});
table.draw();
}
}
function populate_dropdown(dates) {
// make an empty array variable to hold the list of building
var building = [];
// loop through the dates
for (var i = 0; i < dates.length; i++) {
var year = Number($(dates[i]).html().split(' ')[0].split('/')[2]);
var month = Number($(dates[i]).html().split(' ')[0].split('/')[1] - 1);
var day = Number($(dates[i]).html().split(' ')[0].split('/')[0]);
var buildingDate = new Date(year, month, day);
var initialDateRoom = new Date(year, 10, 1);
// now let's calculate the room
var room;
if (buildingDate < initialDateRoom) {
room = Number(year-1) + "/" + year;
} else {
room = year + "/" + Number(year+1);
}
// now let's add that room to the building array (if it's not already in the array!)
if ($.inArray(room, building) == -1) {
building.push(room);
}
}
// now that we're done looping through and building the building list, let's sort the array
building.sort();
// make a variable to hold all the <option> fields for the select dropdown
var options = "";
// loop through the years and make the options fields
$.each(building, function(key,value) {
options += "<option> room " + value + "</option>";
});
// take the new options string that we've built and put it inside the <select> dropdown
$('#filtre_saison').append(options);
}
Just added a function to populate the dropbox in the initComplete property to populate it only after the table is fully initialized (all the row values charged because I need to have different values depending on the values present on first column).
Then, I use the method to build my custom filter and then just redraw the table and Puff!
PS :
Needed to append this if :
if (settings.nTable.id === 'tableBuildings')
to check if it's the specific table I want because I have multiple tables on this page and the filter is applied to every datatable tables present in the page.
Thankyou #Reverend Pete

JQuery Datatables and Bootstrap 3 datepicker

I'm using JQuery datatables to sort some table with data.
I'm using custom items to sort, in my case I have a select element which sorts one of the columns. And this works.
I also have 2 inputs that serve as datepickers.
These pickers have data formatted as same as on the table, so filtering works well, but my question is:
Is possible to filter column based on the range of pickers? So for example:
from 1 sep 2017 to 10 sep 2017?
I'm was looking for some custom function in datatables docs but I found nothing so it's why I'm asking StackOverflow community.
I think I need to check when second date one was selected and then get data of first datepicker and filter column based on this. But to make things easier, when the first picker is selected I will just show the second picker, so the user may know that selecting the first picker will trigger need of selecting the second one also....
$(document).ready(function() {
var table = $('#scroll-wrc-changes-table table').DataTable({
"paging": false,
});
var picker1 = $('#datetimepicker1').datetimepicker({
format: 'DD MMM YYYY',
defaultDate: new Date(),
});
var picker2 = $('#datetimepicker2').datetimepicker({
format: 'DD MMM YYYY',
defaultDate: new Date(),
});
picker1.on('dp.change',function() {
table.columns([3] ).search( this.value ).draw();
});
picker2.on('dp.change',function() {
table.columns([3] ).search( this.value ).draw();
});
// This is just select element
$('#table-select').change(function() {
table.columns([2] ).search( this.value ).draw();
})
});
Maybe this link can help you.
Range Filtering
The idea is to make function for custom filtering.
$.fn.dataTable.ext.search.push(
function( settings, data, dataIndex ) {
var date1 = new Date( $('#datetimepicker1').val() );
var date2 = new Date( $('#datetimepicker2').val() );
var dateData = new Date( data[3] ); // use data from the date column
if ( dateData >= date1 && dateData <= date2 )
{
return true;
}
return false;
});
Hope this help..
Asuming you are using ajax datatable . If not draw idea from this example
Add a row where you can set range for filter as:
<div class="col-md-3"> <label>From:</label> <input readonly="readonly" type="text" id="mindate" class="srchdp"> <i class="fa fa-times-circle-o" id="clear-mindate"></i></div>
<div class="col-md-3"> <label>To:</label> <input readonly="readonly" type="text" id="maxdate" class="srchdp"> <i class="fa fa-times-circle-o" id="clear-maxdate" ></i></div>
<div class="col-md-2"><button class="btn btn-primary" id="filter-record">Filter</button></div>
//initialize datepicker as
$("input:text.srchdp").datetimepicker({
changeMonth: true,
changeYear: true,
yearRange: "-100:+0",
dateFormat: 'mm/dd/yy',
controlType: 'select',
timeFormat: 'hh:mm:ss TT',
})
// now keep a event on filter button click
$(document).on("click", "#filter-record", function () {
assetListVM.search("").draw();
});
// now on ajax request
public ActionResult Get([ModelBinder(typeof(DataTablesBinder))] IDataTablesRequest requestModel, string mindate,string maxdate, string searchbase)
{
DataBaseEntities db = new DataBaseEntities();
IQueryable<Wishlist> query = db.Wishlists;
var totalCount = query.Count();
#region Filtering
// Apply filters for searching
var value = requestModel.Search.Value.Trim();
if (!string.IsNullOrEmpty(searchbase))
{
if (!string.IsNullOrEmpty(mindate) && !string.IsNullOrEmpty(maxdate))
{
DateTime datevaluemin;
DateTime datevaluemax;
var mindateval = DateTime.TryParse(mindate, out datevaluemin);
var maxdateval = DateTime.TryParse(mindate, out datevaluemax);
if (mindateval && maxdateval)
{
var minvalue = Convert.ToDateTime(mindate);
var maxvalue = Convert.ToDateTime(maxdate);
if (searchbase == "CreatedDate")
{
query = query.Where(p =>
p.CreatedDate >= minvalue
&& p.CreatedDate <= maxvalue);
}
}
}
else if (!string.IsNullOrEmpty(mindate))
{
DateTime datevalue;
var mindateval = DateTime.TryParse(mindate, out datevalue);
if (mindateval)
{
var minvalue = Convert.ToDateTime(mindate);
if (searchbase == "CreatedDate")
{
query = query.Where(p =>
p.CreatedDate >= minvalue
);
}
}
}
}
if (requestModel.Search.Value != string.Empty)
{
query = query.Where(p => p.Id.ToString().Equals(value) ||
p.ProductId.ToString().Equals(value) ||
p.MemberId.ToString().Contains(value)
);
}
var filteredCount = query.Count();
#endregion Filtering
#region Sorting
// Sorting
var sortedColumns = requestModel.Columns.GetSortedColumns();
var orderByString = String.Empty;
foreach (var column in sortedColumns)
{
orderByString += orderByString != String.Empty ? "," : "";
orderByString += (column.Data) + (column.SortDirection == Column.OrderDirection.Ascendant ? " asc" : " desc");
}
query = query.OrderBy(orderByString == string.Empty ? " asc" : orderByString);
#endregion Sorting
// Paging
query = query.Skip(requestModel.Start).Take(requestModel.Length);
var data = query.Select(asset => new
{
Id = asset.Id,
ProductId = asset.ProductId,
ProductName = asset.Product.ProductName,
MemberId=asset.MemberId,
CreatedDate = asset.CreatedDate.ToString(),
}).ToList();
return Json(new DataTablesResponse(requestModel.Draw, data, filteredCount, totalCount), JsonRequestBehavior.AllowGet);
}
}
}
this code is not complete hence it doesn't work alone.

FullCalendar fetching events from server not working

I am trying to fetch events from my LocalDB server and have them display on my calendar, but they aren't appearing.
I am using the following method to fetch the events.
public JsonResult GetEvents(double start, double end)
{
var fromDate = ConvertFromUnixTimestamp(start);
var toDate = ConvertFromUnixTimestamp(end);
var eventList = from e in db.Events
select new
{
ID = e.ID,
Title = e.Title,
StartDate = e.StartDate.ToString("s"),
EndDate = e.EndDate.ToString("s"),
EventType = e.EventType,
Hours = e.Hours,
AllDay = true
};
var rows = eventList.ToArray();
return Json(rows, JsonRequestBehavior.AllowGet);
}
private static DateTime ConvertFromUnixTimestamp(double timestamp)
{
var origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
return origin.AddSeconds(timestamp);
}
My calendar is rendered as follows:
#Styles.Render("~/Content/fullcalendar")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/fullcalendar")
<br />
<div id="calendar"></div>
<br />
<script type="text/javascript">
$(document).ready(function () {
$('#calendar').fullCalendar({
header: {
left: 'title',
center: '',
right: 'prev,next today' },
defaultView: 'month',
weekends: false,
editable: false,
events: "/Home/GetEvents/" });
});
</script>
Any help is greatly appreciated.
EDIT:
This is in my web console:
no element found abort:1:1
Use of getPreventDefault() is deprecated. Use defaultPrevented instead. browserLink:37:40278
no element found send:1:1
no element found send:1:1
no element found send:1:1
no element found
GET http://localhost:54802/Home/GetEvents/ [HTTP/1.1 500 Internal Server Error 10ms]
Your response is not conform to fullCalendar expected output. If you see the doc, you understand that each events needs to have at least these parameters:
title
start
In your case the code should be like this:
public JsonResult GetEvents(double start, double end)
{
var fromDate = ConvertFromUnixTimestamp(start);
var toDate = ConvertFromUnixTimestamp(end);
var eventList = from e in db.Events
select new
{
id = e.ID,
title = e.Title,
start = e.StartDate.ToString("s"),
end = e.EndDate.ToString("s"),
eventType = e.EventType,
hours = e.Hours,
allDay = true
};
var rows = eventList.ToArray();
return Json(rows, JsonRequestBehavior.AllowGet);
}
The first problem is, as I think, the name of variables for each event. This not match what fullCalendar is expecting.
With this new one GetEvents method fullCalendar should understand and print your output.

Fixing javascript array initialization

I am trying to initialize an array with another array. The array contains options for loading an RSS feed reader. The user clicks an option button to selection which RSS category to read. Based on the selection I initalize the feed URL and options arrays like this.
feeds = feedsnews.slice(0, feedsnews.length);
options = optionsnews.slice(0, optionsnews.length);
(The entire javascript for this is at the end of the text).
Then I send these arrays to the code for loading the newsreader. This seems to initialize only the first element in the array.
What is the way to initialize the array with all the elements? Are the arrays declared in the right way for the RSS loader to get them?
Here is the code:
<script language="JavaScript">
var feedsnews = [ {title: 'Reuters Top News', url: 'http://feeds.reuters.com/reuters/topNews' }, {title: 'Reuters International',
url: 'http://feeds.reuters.com/reuters/worldNews' }, {title: 'Reuters US News', url: 'http://feeds.reuters.com/Reuters/domesticNews' }];
var optionsnews = {
stacked : true,
horizontal : false,
title : "News"
}
var feedscat = [ {title: 'Catholic News Agency', url: 'http://www.catholicnewsagency.com/rss/news.xml' }, {title: 'Zenit - English', url: 'http://feeds.feedburner.com/zenit/english' }, {title: 'Zenit - Français', url:
'http://feeds.feedburner.com/zenit/french' }];
var optionscat = {
stacked : true,
horizontal : false,
title : "Catholic"
}
</script>
<SCRIPT LANGUAGE="JavaScript">
var feeds=feedsnews.slice();
var options=optionsnews.slice();
function GetSelectedItem() {
feeds=feedsnews.slice(0, feedsnews.length);
options=optionsnews.slice(0, optionsnews.length);
chosen = "";
len = document.f1.r1.length;
for (i = 0; i <len; i++) {
if (document.f1.r1[i].checked) {
chosen = document.f1.r1[i].value
}
}
if (chosen == "") {
alert("No Location Chosen")
}
else if (chosen =="News") {
feeds = feedsnews.slice(0,feedsnews.length);
options = optionsnews.slice(0,optionsnews.length);
}
else if (chosen =="Catholic") {
feeds = feedscat.slice(0,feedscat.length);
options = optionscat.slice(optionscat.length);
}
else if (chosen =="Community") {
}
else if (chosen =="Personal") {
}
else if (chosen =="Professional") {
}
else {
alert(chosen);
}
$("#snews").load("loadnews.php");
}
</script>
HTML (for #snews div)
<div id="snews" style="position:absolute; top:30px; right: 30px; width: 430px; height: 380px; overflow-y: auto; overflow-x: hidden; background: white;">
<?php require("loadnews.php"); ?>
</div> <!-- End snews -->
PHP (loadnews.php)
<!-- ++Begin Dynamic Feed Wizard Generated Code++ -->
<!--
// Created with a Google AJAX Search and Feed Wizard
// http://code.google.com/apis/ajaxsearch/wizards.html
-->
<!--
// The Following div element will end up holding the actual feed control.
// You can place this anywhere on your page.
-->
<div id="feed-control">
<span style="color:#676767;font-size:11px;margin:10px;padding:4px;">Loading...</span>
</div>
<script type="text/javascript">
function LoadDynamicFeedControl() {
new GFdynamicFeedControl(feeds, 'feed-control', options);
}
// Load the feeds API and set the onload callback.
google.load('feeds', '1');
google.setOnLoadCallback(LoadDynamicFeedControl);
</script>
<!-- ++End Dynamic Feed Control Wizard Generated Code++ -->
var optionsnews = {
stacked : true,
horizontal : false,
title : "News"
}
// snip...
options=optionsnews.slice(0, optionsnews.length);
optionsnews is an Object, not an Array. There is no Object.slice method since objects have neither numerical indexing nor inherent ordering.
What is the point of all this .slice()ing? What are you trying to accomplish?

Categories

Resources