So after doing some reading (and not quite understanding a few things) I'm wanting to find out more about derived columns in APEX reports.
The page has a tabular form which shows the tasks they have selected and they can select the time in hours (1-12) and minutes (15min intervals). What they input displays on a report which summarises the time they've allocated to a task from Monday to Friday and also gives a total down the bottom.
A request has been made to be able to not only see the totals for the day down the bottom but also the weekly total for each task on right so I've inserted a derived column.
In the page attributes under Javascript - Function and Global Variable Declaration, I have the following simple function:
var htmldb_delete_message = '"DELETE_CONFIRM_MSG"';
function sum_values(mon, tues, wed, thurs, fri, sat) {
// pass page item names into the function
// $v will get the value from the item name
result = $v(mon) + $v(tues) + $v(wed) + $v(thurs) + $v(fri) + $v(sat);
return result;
}
and then in the derived column HTML attributes I have:
<script>
sum_values(#MONDAY#, #TUESDAY#, #WEDNESDAY#, #THURSDAY#, #FRIDAY#, #SATURDAY#)
</script>
This is not displaying anything and I'm not sure what I'm doing wrong.
Related
Let's say I have the following HTML page;
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
</head>
<body>
<h2 id='invoiceDueDate'>17/08/2018</h2>
<h2 id='paymentStatus'>Yet To pay</h2>
</body>
</html>
I need to check the h2 for the due date, check the payment status for whever its paid or not and if the current day is one week past the invoiceDueDate and is still unpaid then the page needs to display Payment Over Due
It may be obvious but if it is paid then do nothing.
It doesn't necessarily have to use moment.js but it has to use this date format: dd/mm/yyyy
Here is the javascript I have used to try to get it working:
let dueDate = document.getElementById('invoiceDueDate').innerHTML;
console.log(dueDate)
// this get the the due date from the html and I have used console.log to confirm it works
let invoiceStatus = document.getElementById('paymentStatus').innerHTML;
console.log(invoiceStatus)
// this get the theinvoiceStatus from the html and it works
const overDue = moment().add(7, 'days').format('L');
console.log(overDue)
// get the current date and adds 7 days and it works
// todays date isnt the due date so adding 7 on to it doesn't work
if(invoiceStatus.innerHTML === 'Yet To pay'){
if(dueDate >= overDue){
invoiceStatus.innerHTML = "Overdue";
console.log('overdue');
}else{
invoiceStatus.innerHTML = "Un-paid";
console.log('not yet paid');
}
} else {
// do nothing
}
// compares the dueDate to overDue then print it out to the page
The problem with this javascript is it checks the current date then adds 7 days then print the result rather than adding 7 days to the due day THEN printing the result. This is the problem I'm struggling with.
I hope this makes sense.
Edit:
Also is there anyway to do soemthing like this
if(dueDate >= (dueDate + 7 days)){
invoiceStatus.innerHTML = "Overdue";
}
I've made changes and added it to codepen:
https://codepen.io/anon/pen/rZaLvb?editors=1010
It appears that your logic is requiring these to be completely identical. You might want to check instead to see if overdue >= dueDate -- otherwise, it will only count things that are precisely overdue, and not n days overdue.
Also, at some points you're trying to hit the innerHTML of an item's innerHTML.
The changes I would make here:
1) Change:
let invoiceStatus = document.getElementById('paymentStatus').innerHTML;
console.log(invoiceStatus);
To:
let invoiceStatus = document.getElementById('paymentStatus');
console.log(invoiceStatus.innerHTML);
2) Change:
if(dueDate === overDue){
To:
if(overDue >= dueDate){
In Kintone, the time field currently increments by 30 minutes, but is there a way with JavaScript to change this increment, say, by 10 minute increments?
I know this doesn't fit well with Kintone's JavaScript coding guidelines, but would changing the DOM structure of the time field to show 10 minute increments be the correct way to move forward?
Like you said, this is probably possible by editing the DOM, but not the best option since the customization may not work after any update.
As an alternative or a better choice, you can create two drop-down fields, "hour" on one of the them and "minute" on the other field.
Thanks Yuzo
I tried out your solution to see what it's like, and found out it was actually a good alternative.
I currently have it working with the 24 hour clock format, as below.
gif image of customization
(function() {
"use strict";
// "hours" -> field code of Hours field
// "minutes" -> field code of Minutes field
// "time" -> field code of Time field
kintone.events.on(['app.record.create.submit','app.record.edit.submit','app.record.index.edit.submit'], function (event) {
var hourvalue = event.record.hours.value;
var minutevalue = event.record.minutes.value;
event.record.time.value = hourvalue + ":" + minutevalue;
return event;
});
})();
My team prefers to work with 12 hour clock format though, so I added in a radio button field to represent AM and PM. I also changed the drop down to only include selections from 0 to 11.
I edited my code a bit more so that the selected hour number will get a +12 before being entered into the time field, but I keep getting an error, "event.record['time'].value is invalid.". Not really sure why this should be happening. This is my new code:
(function() {
"use strict";
// "hours" -> field code of Hours field
// "minutes" -> field code of Minutes field
// "time" -> field code of Time field
// "ampm" -> field code of radio button field that has selections of AM and PM
kintone.events.on(['app.record.create.submit','app.record.edit.submit','app.record.index.edit.submit'], function (event) {
var hourvalue = event.record.hours.value;
var minutevalue = event.record.minutes.value;
if (event.record.ampm.value == "PM"){
hourvalue = hourvalue + 12;
}
event.record.time.value = hourvalue + ":" + minutevalue;
return event;
});
})();
I did some test regarding what you are doing.
It seems like the error you are seeing appears only when the field type that you are returning
to in the script does not match the actual field type that you have placed in the form.
So I assume when you changed your form to make it as the 12 o'clock format,
you might have changed the field that you put the value into to a time field,
which before it was a text field.
Can you check into it?
I will put a link below regarding the field types just for your reference
kintone developer network - Field Types https://developer.kintone.io/hc/en-us/articles/212494818-Field-Types
I think the drop-down field returns a string value.
Therefore, you need to convert it to a number by using parseInt function before hourvalue like hourvalue(hourvalue + 12). Thanks.
I am trying to add span element before the fc-center class of full calendar so I need to display the month in that span that I want to add, in the eventAfterAllRender i wrote this code
var titleHead = new Date( $('#calendar').fullCalendar('getDate') );
var month_int = titleHead.getMonth();
$(".fc-center").before('<label>' + month_int + '</label>')
and each time I press the prev button or the next button it renders the span again, so if I change the view five times, it renders 5 spans
There is a better way to get the same effect, using the built-in date formatting options:
views: {
month: { titleFormat: 'M - MMMM YYYY' },
week: { titleFormat: 'M - MMM D YYYY'},
day: { titleFormat: 'M - MMM D YYYY'}
},
This adds the month number to the start of the displayed date in each of the regular view types.
See http://jsfiddle.net/sbxpv25p/75/ for a working example.
You can remove the other code you wrote in eventAfterAllRender (as shown in the question).
Also see https://fullcalendar.io/docs/text/titleFormat/ and https://fullcalendar.io/docs/views/View-Specific-Options/ for more information on the syntax above. Also see http://momentjs.com/docs/#/displaying/ to understand what the formatting tokens do.
P.S. It's worth noting that your previous attempt had a number of issues, beyond what you mentioned in the question:
1) It renders multiple times, as mentioned, because you simply kept appending more labels without checking whether there was one already there. eventAfterAllRender runs whenever events are refreshed, which is done automatically when the view or date changes
2) fullCalendar's getDate method (see https://fullcalendar.io/docs/current_date/getDate/) returns a momentJS object, from which you can directly get the current month (http://momentjs.com/docs/#/get-set/month/), so there's absolutely no reason to then turn it into a JS Date object, this was just wasted effort.
3) It fetched the wrong month for display purposes - months in the JS Date objects are zero-based, so for example in December it would display 11 instead of 12. You'd have needed to add 1 to any value you retrieved.
4) It's badly aligned against the date and looks ridiculous. You can use .prepend() to insert it inside the .fc-center element, then it's at the same height.
If you still wanted to implement something like this, in case you want to add other content to the title bar which isn't the month, then you should move your code outside the calendar config, to just after you declare fullCalendar, so that it only executes once. Here is what you should put there - it's different to your code above because it fixes all the points 1-4 above:
var dt = $('#calendar').fullCalendar('getDate');
var month_int = dt.month() + 1;
$(".fc-center").prepend('<label>' + month_int + ' </label>');
See http://jsfiddle.net/sbxpv25p/77/ for a demo of this.
I'm using the fromNow function from moment.js library to display time elapsed from a specific date/time (e.g. '16 hours ago'). I use this within a table on multiple rows within my web app.
This part works fine, but I need the time to count continuously and for several rows (50 - 60 and growing). How do I get the time to count continuously and efficiently? I say efficiently because, I've read that using interval may be a bad idea so I'm not sure and I need help understanding.
This is how I create a cell which holds the elapsed time:
newCell = row.insertCell(++cellIndex);
newText = document.createTextNode(moment(data.checkintime).fromNow());
newCell.appendChild(newText);
Assuming the code you posted is correct, you can save the updated time in a variable and update all the rows. In that way, it's the same time that will display for all the rows and that time would just have to be done in one time:
var updatedTime = moment(data.checkintime).fromNow();
newCell = row.insertCell(++cellIndex);
newText = document.createTextNode(updatedTime);
newCell.appendChild(newText);
If you want the timestamp to continuously update, look into a library such as TimeAgo.
With your current code, simply change the text node to match timaeago's syntax <abbr title='{timestamp}' class='timeago'> and add the following javascript to the bottom of your page
jQuery(document).ready(function() {
jQuery("abbr.timeago").timeago();
});
This will continuously update the timestamp ("a moment ago", "2 minutes ago"....) which I believe is what you're looking for
I am trying to find the best approach to comparing date/times using Javascript in order to prevent double booking on a SharePoint calendar. So I load an array with items that contain each event, including their start date/time and end date/time. I want to compare the start date/time and end date/time against the start/end date/times in the object, but I am not sure how to ensure that dates will not lapse.
like:
//date that is created from user controls
var startDate = new Date(startDat + 'T' + startHour + ':' + startMin + ':00');
var endDate = new Date(endDat+ 'T' + endHour+ ':' + endMin+ ':00');
for ( var i = 0; i < allEvents.length; i++ ) {
var thisEvent = allevents[i];
//having trouble with the compare
//i have tried silly ifs like
if (thisEvent.startDate >= startDate && thisEvent.endDate <= endDate) {
// this seems like I am going down the wrong path for sure
}
}
I then tried breaking apart the loaded object into seperate values (int) for each component of the date
var thisObj = { startMonth: returnMonth(startDate), startDay: returnDay(startDate), etc
but I am not sure this isn't just another silly approach and there is another that just makes more sense as I am just learning this.
I have a similar requirement in progress but chose to solve it at the booking stage, with jQuery/SPServices.
The code is still in build (ie not finished) but the method may help.
I attach an event handler to a column, then on selection, fetch all the dates booked in the same list to an array, then display that array on a rolling 12 month cal, as below.
I'm not checking to ensure a new booking doesn't overlap but a quick scan through the array on Pre-Save would provide a strict Go/No Go option for me. Relies on client side JS though, so not going to work in a datasheet or web services context.