I've tried to add a date range search for the jQuery DataTable. The date range filter works fine and the normal Search over all Columns/Rows is also working.
My Problem is at the moment that the refresh of the table (Event) executes only after the Change in the normal search. So i need a Event which repaints / redraws / updates the Table.
So I need a call for something like a refresh at the datatable.
Here is my current code:
window.onload = function () {
$(document).ready(function () {
try {
var table = $('#MainContent_gridClaim').dataTable();
} catch (Err) { };
});
$('.datepicker').pickadate({
selectMonths: true, // Creates a dropdown to control month
selectYears: 15 // Creates a dropdown of 15 years to control year
});
};
$.fn.dataTable.ext.afnFiltering.push(function (settings, data, indx) {
//Min Max Document
var min = document.getElementById("min").value;
var max = document.getElementById("max").value;
if (min === "" || max === "") {
return true;
}
//Res Min Max
var resMin = min.split(".");
var resMax = max.split(".");
//Min Max Date
var dMin = new Date(resMin[2],resMin[1],resMin[0],0,0,0,0);
var dMax = new Date(resMax[2],resMax[1],resMax[0],0,0,0,0);
var resData = data[5].split(".");
var resYear = resData[2].split(" ");
var dJet = new Date(resYear[0], resData[1], resData[0], 0, 0, 0, 0);
var minSec = dMin.getTime();
var maxSec = dMax.getTime();
var actualSec = dJet.getTime();
if (minSec<=actualSec&&actualSec<=maxSec) {
return true;
} else {
return false;
}
});
You need to call
$('#MainContent_gridClaim').dataTable().draw();
when you change the date range. I don't know your date picker plug-in, but you need to add dataTable.draw() call to something like onChange of the datepicker.
There is a similar example https://datatables.net/examples/plug-ins/range_filtering.html
Related
So I have a function called shift that returns what shift the user is in based on the time.
When I run the program the time and dates go into their cells in my spreadsheet however my shift value does not. I know my shift function returns a value because I've tested it using the test function and the correct value appears in my logs. Here is my code:
const timezone = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
/** #returns {string} */
function timestamp() {
var timestamp_format = "HH:mm:ss";
return Utilities.formatDate(new Date(), timezone, timestamp_format);
}
/** #returns {string} */
function datestamp() {
var datestamp_format = "yyyy-MM-dd";
return Utilities.formatDate(new Date(), timezone, datestamp_format);
}
function shift() {
var shift;
const dt = timestamp();
if(dt > "08:00:00" && dt < "13:59:00"){
shift = "1";
}
return shift;
}
function test(){
shifts = shift();
console.log(shifts);
}
/* #Process Form */
function processFormHood(formObject) {
var url = "GOOGLE DOCS URL";
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName("SHEETNAME");
ws.appendRow([
datestamp(),
timestamp(),
shift()])
}
The last function takes values from my HTML form and writes it into my spreadsheet. An example would be "formObject.value," I have attempted to do this with my shift function but it did not work. The cell it is supposed to be in gets skipped and everything after it gets filled.
It seems all I had to do was instead of having
function shift() {
var shift;
const dt = timestamp();
if(dt > "08:00:00" && dt < "13:59:00"){
shift = "1";
}
return shift;
}
I needed to do was make it return without the use of varables:
function shift() {
const dt = timestamp();
if(dt > "06:00:00" && dt < "13:59:99"){
return 1;
}
else if(dt > "14:00:00" && dt < "21:59:59"){
return "2,3";
}
}
I have a Google Sheet with 5 columns and dates of the last check. I want to only keep the entries when the number of days since the last check is > 10 days.
The Sheet: https://docs.google.com/spreadsheets/d/1nD7CXraydrAwOh7q7QFDLveVW76wRNU0ago4h-ORn8U/edit?usp=sharing
function check(){
/** Variables **/
var ss = SpreadsheetApp.getActiveSpreadsheet(); var sh1 = ss.getSheetByName('Data Processing');
/** Remove duplicates **/
var sh1data = sh1.getDataRange().getValues();
var sh1newData = [];
for (var i in sh1data) {
var row = sh1data[i];
var duplicate = false;
for (var j in sh1newData) {
/* DATE */
var today=new Date().valueOf();
var sec=1000; var min=60*sec; var hour=60*min; var day=24*hour; // Do the conversions
var sh1DateChecked = sh1newData[j][4].valueOf();
var diff=today-sh1DateChecked;
var days=Math.floor(diff/day); // Number of Days since the last check
if(row[0] == sh1newData[j][0] && row[1] == sh1newData[j][1] && days < 10)
{ duplicate = true; } }
if (!duplicate) { sh1newData.push(row);
}
}
sh1.clearContents();
sh1.getRange(1, 1, sh1newData.length, sh1newData[0].length).setValues(sh1newData);
}
This solution ignores the code's mention of "duplicates" and focuses on your stated question of removing dates less than 10 days old. However, if you need to remove duplicates as well, it can be easily added.
I propose you put your condition in a function that takes a row of data as input and returns a boolean (true/false) such as
function dateCheckedOlderThan10Days(row) {
return getDays(row[4]) > 10;
}
function getDays(date) {
const sec = 1000;
const min = 60 * sec;
const hour = 60 * min;
const day = 24 * hour;
return Math.floor((new Date() - date)/day);
}
(Note how you can completely extract the getDays function from your main function. That reduces the amount of code you have to think about inside each function definition.)
This function will fit perfectly into Array.prototype.filter, and the naming of the function makes it very clear what you expect to happen.
const dataOlderThan10Days = ss.getSheetByName('Data Processing')
.getDataRange()
.getValues()
.filter(dateCheckedOlderThan10Days);
Here is the checked function refactored into several functions:
Code.js
function check() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const dataSheet = ss.getSheetByName('Data Processing');
const data = dataSheet.getDataRange().getValues();
const dataOlderThan10Days = data
.slice(1) // removes header row; comment out if you don't have a header row
.filter(dateCheckedOlderThan10Days);
dataSheet.clearContents();
//dataOlderThan10Days.unshift(data[0]); // <-- if you want to restore the headers
setData(dataSheet, dataOlderThan10Days);
}
function dateCheckedOlderThan10Days(row) {
return getDays(row[HEADINGS.DATE_CHECKED]) > 10;
}
const HEADINGS = {
FIRST_NAME: 0,
LAST_NAME: 1,
SALARY: 2,
AGE: 3,
DATE_CHECKED: 4
};
function setData(sheet, data) {
sheet.getRange(1, 1, data.length, data[0].length).setValues(data);
}
function getDays(date) {
const sec = 1000;
const min = 60 * sec;
const hour = 60 * min;
const day = 24 * hour;
return Math.floor((new Date() - date)/day);
}
Highcharts hour data aggregation flow
follows the next rules: 01 AM = 01:00 + 01:15 + 01:30 + 01:45. (example). So all points between current hour and the next one.
I want it to follow the rule: 01 AM = 00:00 + 00:15 + 00:30 + 00:45
I didn't find a possibility to do that in datagrouping options of library.
Now I'm thinking about hack to modify serie.groupedData object (adding 1 hour to time present there), but unfortunately, even though data is modified it still display old values in chart
chartConfiguration.xAxis[0].events = {
setExtremes(event) {
this.series.forEach(serie => {
if (serie.hasGroupedData && serie.currentDataGrouping.unitName == "hour") {
let groupedData = serie.groupedData.map(dataPiece => {
dataPiece.x = dataPiece.x + 3600000;
return dataPiece;
});
serie.update(groupedData);
}
})
}
};
This code changes x value of all the points to one hour earlier if 1 hour data grouping is applied:
chart: {
events: {
render: function() {
if (redrawEnabled) { // prevent infinte recursive loop - this.redraw() calls render event
redrawEnabled = false;
var series = this.series[0],
isHourUnit = series.currentDataGrouping.unitName === 'hour';
if (isHourUnit && !hourOffsetApplied) {
// change the data
series.setData(data.slice().map((p) => [p[0] - hour, p[1]]), false);
hourOffsetApplied = true;
} else if (!isHourUnit && hourOffsetApplied) {
// resotre the original data
series.setData(data, false);
hourOffsetApplied = false;
}
this.redraw();
redrawEnabled = true;
}
}
}
},
Live demo: http://jsfiddle.net/BlackLabel/z850035n/
If you change dataGrouping.units to ['day', [1]] point are displayed without time offset.
Let's say there's a system that shows date availability for events. We have a main date range where all events go. Events can be date ranges themselves too.
Example:
[Date X]========================================[Date Y]
[A]=====[A] [B]=====[B][C]=====[C]
[ Event A ][ Open ][ Event B ][ Event C ]
Where Date X and Date Y are the main date range where events go. And A,B, and C are events that have been scheduled.
How can I efficiently retrieve the open date range?
Example 2:
var rangeStart = new Date("04-01-2016");
var rangeEnd = new Date("04-31-2016");
var eventAStart = new Date("04-01-2016");
var eventAEnd = new Date("04-06-2016");
var eventBStart = new Date("04-15-2016");
var eventBEnd = new Date("04-30-2016");
I need to return something like:
var availableRangeStart = "04-07-2015";
var availableRangeEnd = "04-14-2016";
because these are the dates in the main range that are not overlapped by "event" ranges.
To be exact on what I am trying to do:
My app is a trip planner where the user sets the dates for their trip and then adds different destinations to that trip that have their own dates. (User is going on a trip to Europe April 1st to April 30th, they will be in Paris on April 1st to April 6, then they will be in London April 15th to April 30th). But the user has not planned anything from April 7th to April 14th. I am trying to return these dates so that when they add a new destination, the dates are pre-filled.
I just give you an algorithm because the final implementation depends of your code.
var aprilAvailableDays = [true, true, true, etc...] // a boolean for each day
aprilEvents.forEach(function (event) {
for (var i = event.startDay; i <= event.endDay; i++) {
aprilAvailableDays[i] = false;
}
});
Here is a solution that returns from/to periods that are free:
// Helper function
function addDays(date, days) {
return new Date(date.getTime() + days * 24*60*60*1000);
}
// Main function
function gaps(period, events) {
events = events.slice(0).filter(function (a) {
// Exclude events which are outside the main period
return a.to >= period.from && a.from <= period.to;
}).sort(function (a, b) {
// Sort events by their starting date
return a.from - b.from;
});
var result = events.reduce(function (result, curr) {
if (curr.from - result.free > 0) {
// gap found
result.gaps.push({
from: result.free,
to: addDays(curr.from, -1)
});
}
if (curr.to - result.free >= 0) {
// first free day is after this event
result.free = addDays(curr.to, 1)
}
return result;
}, { gaps: [], free: period.from } );
// Potentially add gap between last event end period-end
if (period.to - result.free >= 0) {
result.gaps.push({
from: result.free,
to: period.to
});
}
return result.gaps;
}
// Sample data:
var period = {
from: new Date('2016-01-01'),
to: new Date('2016-12-31')
};
var events = [
{ from: new Date('2016-02-01'), to: new Date('2016-02-29') },
{ from: new Date('2016-03-01'), to: new Date('2016-03-15') },
{ from: new Date('2016-04-16'), to: new Date('2016-04-30') },
];
// Call to function
var res = gaps(period, events);
// Output in snippet
document.write('<pre>' + JSON.stringify(res, null, 4));
I have an HTML page where I have applied some Knockout bindings to some elements:
<td class="tepvval" data-bind="text: tepv"></td>
<td class="dateval" data-bind="text: dueIn(due)"></td>
In the second element, I call a function to populate the data content of the element. I'm trying to do the same for the style of the element, but I'm having issues. I need to call a function to compute the difference between the date (due) and today, and then return the color I want to use for the background of the element - green is due more than 30 days, yellow is 30-15 days, orange 15-1 days, red is overdue.
I tried using
<td class="dateval" data-bind="text: dueIn(due),
style: { backgroundColor: colorDue(due) }"></td>
but that doesn't work.
what am I missing in the syntax?
here is the function code I'm calling in colorDue:
function colorDue(due) {
rd = 1;
od = 15;
yd = 30;
var difference = dateDiff(due);
if (difference>yd) { color="green"; }
else if (yd>difference && difference>od) { color="yellow"; }
else if (od>difference && difference>rd) { color="orange"; }
else if (difference <=rd) { color="red"; }
return color;
}
function dateDiff(due) {
var df, ymd, now, dateStr, diff;
df = due.split(" ");
ymd = df[0].split("-");
now = new Date();
dateStr = new Date(ymd[0],ymd[1],ymd[2],17,0,0);
diff = dateStr.getTime()-now.getTime();
diff = diff/86400000;
return diff;
}
Your problem is here:
dateStr = new Date(ymd[0],ymd[1],ymd[2],17,0,0);
In js (don't ask why), month starts at 0 (while day and year starts at 1...). See doc
month Integer value representing the month, beginning with 0 for
January to 11 for December.
So you need a -1 here:
dateStr = new Date(ymd[0],ymd[1] -1,ymd[2],17,0,0);
There are other stuff that you should change here, like declaring your variables local:
function colorDue(due) {
var rd = 1;
var od = 15;
var yd = 30;
var color = "";
//...
}