datetime picker in Tabulator? - javascript

I want to use pure javascript datetime picker in Tabulator.js. Usually I use Materializecss but they don`t provide datetime picker. Only date or time. So I had to find one. I chose rome although I liked better dtsel - it got much nicer time picker but I have not found cdn for it.
I found that Tabulator provides a way to implement customer editors. In my code (see jsFiddle) it is the editor:dateEditorOriginal function. It works nicely and even provides build in calendar. Could someone tell where the calendar comes from? Tabulator or moment?
But I need datetime so please have have a look at the var dateEditor. I tried to use rome picker but I am not able to make it work. I am able to select the date and time but it will not pass it to Tabulator.
var dateEditor = function(cell, onRendered, success, cancel, editorParams){
//cell - the cell component for the editable cell
//onRendered - function to call when the editor has been rendered
//success - function to call to pass the successfuly updated value to Tabulator
//cancel - function to call to abort the edit and return to a normal cell
//editorParams - params object passed into the editorParams column definition property
//create and style editor
var editor = document.createElement("input");
//var cellValue = cell.getValue()
var cellValue = moment(cell.getValue(), "DD-MM-YYYY HH:mm").format("DD-MM-YYYY HH:mm")
// editor.setAttribute("type", "date");
var cal
//create and style input
editor.style.padding = "3px";
editor.style.width = "100%";
editor.style.boxSizing = "border-box";
//Set value of editor to the current value of the cell
// editor.value = moment(cell.getValue(), "YYYY-MM-DD HH:mm").format("YYYY-MM-DD HH:mm")
//editor.value = cellValue
//set focus on the select box when the editor is selected (timeout allows for editor to be added to DOM)
onRendered(function(){
//console.log(cellValue)
cal = rome(editor,{
"inputFormat": "DD-MM-YYYY HH:mm",
"initialValue": cellValue,
"timeInterval": 600,
"weekStart": 1
})
// editor.focus();
// editor.style.css = "100%";
});
//when the value has been set, trigger the cell to update
function successFunc(){
var tmp = editor.value
console.log(cal.getDate())
console.log(tmp)
console.log(cell.getValue())
// success(tmp)
// success(moment(editor.value, "DD-MM-YYYY HH:mm").format("DD-MM-YYYY HH:mm"));
}
editor.addEventListener("change", successFunc);
editor.addEventListener("blur", successFunc);
//return the editor element
return editor;
};
Could someone help me to implement pure javascript datetime picker in Tabulator?
Here is jsFiddle. The column From uses my implementation of datetime picker and column To uses original dateEditor.
The issue I am facing to is that with the current set up the correct date is selected, passed to the input field but not to the Tabulator. It is my explanation what is happening if I am correct. Once the date & time selection finished I want it to see it in the Tabulator.

If you don't have to use Rome, I can suggest using flatpickr instead.
var dateEditor = (cell, onRendered, success, cancel, editorParams) => {
var editor = document.createElement("input");
editor.value = cell.getValue();
var datepicker = flatpickr(editor, {
enableTime: true,
dateFormat: "j-n-Y H:i",
onClose: (selectedDates, dateStr, instance) => {
success(dateStr);
instance.destroy();
},
});
onRendered(() => {
editor.focus();
});
return editor;
};
Here is an example:
https://jsfiddle.net/fazLh6v0/

you must call success() to update Tabulator.
for some reason (that I spent WAY too much time on but didnt get an answer), success() in your example does NOT like to be called with the existing cell value ?
So I added :
(cell.getValue() != cal.getDateString()) && success(cal.getDateString());
It also didnt like that your 2nd row doesnt have a timecode in it, so the first choice of using the time selector is ignored, and sets it to 00:00, then the 2nd (and further applications) go as expected.
Solving these other problems, is up to you I guess, coz I dont use rome.
I just use the builtin <input type=datetime-local>

Your Problem is that the blur event (You use it to capture the finish of the user) triggers already when the user clicks on the calendar - so before his choice is processed.
The only solution I could find is to use another framework.
With flatpickr (It also has a time feature and looks much nicer) for example, you can define a close event that triggers the success function.
(just like Tim's solution)

Related

Get the date variable in Fullcalendar.js and Datepicker

I am working to add datepicker to fullcalendar so users can skip to a desired date. The issue I am having is getting the date variable from datepicker to work with calendar.gotoDate(). I am sure this is something simple, but I only know enough about javascript to struggle by.
I currently have a script using datepicker like so:
jQuery(function($) {
$('#datepicker').datepicker({
dateFormat: 'yy-mm-dd',
});
function get_datepicker() {
var date = $('#datepicker').datepicker('getDate');
return date;
};
});
After I call fullcalendar (which is working flawlessly) I am trying to add a listener for the date change.
document.getElementById('datepicker').addEventListener('change', function() {
get_datepicker();
calendar.gotoDate(date);
});
since fullcalendar has removed jquery, it makes it a bit tougher (for me at least) to implement other scripts like datepicker, which normally wouldn't make sense to load, but in Wordpress, it is already there...
You are never setting the date variable inside the change listener. Either of the following should work.
document.getElementById('datepicker').addEventListener('change', function() {
let date = get_datepicker();
calendar.gotoDate(date);
});
OR
document.getElementById('datepicker').addEventListener('change', function() {
calendar.gotoDate(get_datepicker());
});

fullcalendar: is there a way to call dayRender only after i load my events via events function

i'm using fullcalendar in a web application i"m building.
i load my events with events function and ajax.
here is my code:
var ajaxData;
var eventsJsonArray;
var json_backgrundColor;
var json_iconstring;
//alert('Hello! 1!');
$(document).ready(function () {
$('#calendar').fullCalendar({
header: {
left: 'prev',
center: 'title',
right: 'next,month,agendaWeek,agendaDay'
},
//custom events function to be called every time the view changes
events: function (start, end, timezone, callback) {
var mStart = start.format('M')
var yStart = start.format('YYYY')
$.ajax({
url: '$getMonthDataUrl',
type: 'GET',
data: {
startDate: start.format(),
endDate: end.format()
},
error: function () {
alert('there was an error while fetching events!');
},
success: function (data) {
alert('nice!!');
ajaxData = data;
json_iconstring = ajaxData['iconString'];
json_backgrundColor = ajaxData['Calendar_cell_background_color'];
eventsJsonArray = ajaxData['all_Events_For_The_Month'];
callback(eventsJsonArray); //pass the event data to fullCalendar via the supplied callback function
}
});
},
fixedWeekCount: false,
showNonCurrentDates: false,
dayRender: function (date, cell, view) {
console.log(json_backgrundColor);//this brings eror because json_backgrundColor is undefined
var cellDate = date.format('D');
if (date.format('M') == view.start.format('M')) //cheacking is this day is part of the currrent month (and not prev/next month)
{
alert(cellDate);
cell.css('background-color', json_backgrundColor[cellDate]);//this brings eror because json_backgrundColor is undefined
}
},
})
});
when i load my events via ajax i'm also getting the information about which background color each cell should get. i can only get this info via the events ajax request.
the problem is that when the dayRender is running, i still don't have the background color data. (json_backgrundColor is undefined).
is there a way that dayRender will run after the events calendar will stop running? or any other code that will fix my problem.
many thanks!!
Your problem is that the "dayRender" callback runs after the view is changed (changing the date using prev/next counts as changing the view, for this purpose), but before the events for the new view have been downloaded and rendered. That's why your json_backgrundColor array is undefined.
Since you mentioned that the colour to be used depends on the exact nature of the events currently scheduled for that specific day, we need to find something that we can run after all the events, and this colour data, have been downloaded.
Inspecting the HTML, we can see that the table cells used to draw each day all have the CSS class "fc-day" applied. They also have a data-date property containing the day that they relate to. Finally, days that are disabled (outside the main month, due to you setting showNonCurrentDates:false) have an extra class of "fc-disabled-day" applied. We can use these pieces of information to identify the cells we want to change, without having to use the dayRender callback.
The eventAfterAllRender callback runs once when all the events have been rendered. Therefore this seems like a good place to alter the background colours of the cells:
eventAfterAllRender(function(view) {
//loop through each non-disabled day cell
$('.fc-day:not(.fc-disabled-day)').each(function(index, element) {
//set the background colour of the cell from the json_backgroundColor arrray, based on the day number taken from the cell's "data-date" attribute.
$(this).css('background-color', json_backgroundColor[moment($(this).data("date")).format("D")]);
});
}
Note that I have renamed json_backgrundColor to json_backgroundColor to correct the spelling error.
N.B. This is brittle in the sense that it relies on the class names that fullCalendar uses internally to represent the day cells. If fullCalendar decides to do this differently in a future release, it will break (whereas if we were able to use the fullCalendar API via the designated callbacks, they would likely maintain consistency despite internal changes, or at least document any change). But it's pretty key to the Month view, so realistically it's not likely to change any time soon - you would just have to remember to test it if you update your fullCalendar version.
if anyone still wondering you can use dateSet option like
datesSet: event => {
var from = moment(event.start).format('YYYY-MM-DD');
var to = moment(event.end).format('YYYY-MM-DD');
dateStatus = getEachDateStatus(from, to);
//{'2022-11-10' : 'fullbooked', '2022-11-09' : 'halfBooked'};
Object.keys(dateStatus).forEach(key => {
$('td[data-date="'+key+'"]').addClass(dateStatus[key]);
});
},
Instead of relying on dayRender, you should create background color events based on your ajax:
events = [
...
{ date: date
color: ...
rendering: 'background'
className: 'my-class'
}]
You can transform events using css any way you like, with or without the rendering: 'background' option.

Calculate on the Fly While Still Allowing Input - Javascript API

I have a Mysql table called invoice_detais and I am using a PHP code generator PHPRUNER to retrieve, add, and edit data from my database. In the page that is used for adding a new record in invoice_details, I set the following Javascript event:
var ctrlPrice = Runner.getControl(pageid, 'Price');
var ctrlQuantity = Runner.getControl(pageid, 'Quantity');
var ctrlTotal = Runner.getControl(pageid, 'Total');
function func() {
ctrlTotal.setValue(Number(ctrlPrice.getValue()) - Number(ctrlQuantity.getValue()));
};
ctrlPrice.on('keyup', func);
ctrlQuantity.on('change', func);
The quantity is calculated on fly, but I can not edit the field, and sometimes I need it to be inserted manually without calculation. I mean to set this field to the auto-calculated value but also allow free input.
Please help.

Auto update timeAgo value from submitted date

EDIT: I think I should make things more obvious.
What I am trying to do is to make the function that displays the "time ago" from the submitted date of the post auto refresh every minute so that it stays relatively accurate even if the template is not re rendered.
I'd like to auto update my timeago value in my template but it is not working.
I've tried to set up my code with a reactive function, based on the answer to a similar question (https://stackoverflow.com/a/17933506)
Here's my code:
var timeAgoDep = new Deps.Dependency(); // !!!
var timeAgo;
var timeAgoInterval;
Template.postItem.created = function() {
function getTimeago() {
//var now = new Date();
timeAgo = moment(this.submitted).twitter();
timeAgoDep.changed(); // !!!
};
getTimeago(); /* Call it once so that we'll have an initial value */
timeAgoInterval = Meteor.setInterval(getTimeago, 5000);
};
Template.postItem.posted = function() {
timeAgoDep.depend(); // !!!
return timeAgo;
};
Template.postItem.destroyed = function() {
Meteor.clearInterval(timeAgoInterval);
};
I'm pretty sure that the problem comes from this.submitted because if I assign timeAgo = now for example, it will display the time and update like it's supposed to.
I also know that moment(this.submitted).twitter() works fine because when all I do is return it through a helper, it works.
A much better way to do this is to just embrace Meteor's reactivity and render time-dependent values reactively. In your case, the problem is that you are invalidating the dependency once every 5 seconds for each postItem rendered, which will quickly turn into a huge mess.
See https://github.com/mizzao/meteor-timesync for a package that provides reactive time variables on the client (and they are synced to server time too!) It's basically doing what you want, but in a cleaner way. (Disclaimer: I wrote this package.)
You can use moment in the same way to compute the actual string to display. For example, get rid of all the other stuff and just use
Template.postItem.posted = function() {
return moment(this.submitted).from(TimeSync.serverTime());
}
The moment().twitter() extension doesn't seem like a good choice because it only uses the current client time and doesn't allow you to pass in a specific (i.e. server-synced) time or reactive value.

jQuery function evaluation timing

I have a page that uses the jQuery UI datepicker. I'm trying to make the following happen on my page:
click on the date field -> calendar pops up (datepicker takes care of this)
click on a calendar day -> ajax request fires off, does some server-side calculations (checking for scheduling conflicts and the like), and displays a warning if it's a busy day
It's not exactly a validation, as the intent is to display a warning but still allow the user to submit whatever day they want.
What I have so far fires off the ajax, but with the wrong date. I think it's grabbing the date at page-load rather than when a calendar-day is clicked, so I'm guessing datepicker('getDate') is being evaluated at load time. How can I construct this to evaluate dynamically? Here's the current version (in coffeescript):
jQuery ->
$("#rescheduler").click ->
$("td[data-handler='selectDay'] a").click ->
id = getUrlVars()["booking_id"]
newDate = new Date(datepicker.datepicker('getDate'))
postData = {}
postData['booking_id'] = id
postData['date'] = newDate
$.post '/path/to/check_stuff', postData, ((data) -> doStuff), "json"
or, if you prefer native javaScript:
jQuery(function() {
return $("#rescheduler").click(function() {
return $("td[data-handler='selectDay'] a").click(function() {
var id, newDate, postData;
id = getUrlVars()["booking_id"];
newDate = new Date(datepicker.datepicker('getDate'));
postData = {};
postData['booking_id'] = id;
postData['date'] = newDate;
return $.post('/path/to/check_stuff', postData, (function(data) {
return doStuff;
}), "json");
});
});
});
I suspect that what is happening is the date picker sets the date as, say, March 2, 2014 but this is set as UTC time so the value is something like March 2, 2014 00:00:00. Then when you create the new date from the passed in values your timezone gets added to the mix, causing the date to appear to be off.
If this is so (try logging some of the values to see what, exactly, you are working with) then you need to modifying the date picker value to account for time zone.
Something like:
localDate = new Date(dateToFix); //dateToFix would be the value from the date picker
localTime = localDate.getTime();
localOffset = localDate.getTimezoneOffset() * 60000;
adjustedDate = new Date(localTime + localOffset);

Categories