DataTables - filtering based on time span - datatables

I have a column with data, within the datatables, similar to the below:
0500-1300
0500-1430
0600-0915
0600-1000
0600-1100
0600-1115
0600-1130
0600-1200
0600-1215
0600-1300
0600-1315
I would like a filter not too dissimilar from http://yadcf-showcase.appspot.com/dom_bootstrap_time.html where someone can pick a FROM time and a TO time, which would then filter the data.
Let's say say someone chooses:
FROM: 0600
TO: 1100
Then only 3 would show. However if I chose:
FROM: 0500
TO: 1400
All would show. Is such a thing possible? Would the plugin from the site above be what I am after?

Try this:
const timeStringToInt = (time) => {
const hoursMinutes = time.split(/[.:]/);
const hours = parseInt(hoursMinutes[0], 10) * 60;
var minutes = parseInt(hoursMinutes[1], 10);
return hours + minutes;
}
$.fn.dataTable.ext.search.push(
(settings, data, dataIndex) => {
const min = timeStringToInt($('#timeFrom').val());
const max = timeStringToInt($('#timeTo').val());
const start = timeStringToInt(data[0]);
const end = timeStringToInt(data[1]);
return start >= min && end <= max;
}
);
You might need to alter your function depending upon the position of the hours columns. Working JSFiddle here.
EDIT
After looking at your data a little more I made a mistake in my initial answer, this should do it:
const timeStringToInt = (time) => {
const hoursMinutes = time.split(":");
const hours = parseInt(hoursMinutes[0], 10) * 60;
var minutes = parseInt(hoursMinutes[1], 10);
return hours + minutes;
}
const stringToInt = (time) => {
var minutes = parseInt(time.slice(-2), 10);
const hours = parseInt(time.slice(0, -2), 10) * 60;
return hours + minutes;
}
$.fn.dataTable.ext.search.push(
(settings, data, dataIndex) => {
const min = timeStringToInt($('#timeFrom').val());
const max = timeStringToInt($('#timeTo').val());
const timeParts = data[0].split("-");
const start = stringToInt(timeParts[0]);
const end = stringToInt(timeParts[1]);
return start >= min && end <= max;
}
);
Updated JSFiddle here.
Hope that helps :-)

Related

Not sure how LoadItems work in the React-Native-Calendars example

I'm trying to use the react-native-calendars library in my code.
I'm trying to understand this snipped of the code here
loadItems = (day: DateData) => {
const items = this.state.items || {};
setTimeout(() => {
for (let i = -15; i < 85; i++) {
const time = day.timestamp + i * 24 * 60 * 60 * 1000;
const strTime = this.timeToString(time);
if (!items[strTime]) {
items[strTime] = [];
const numItems = Math.floor(Math.random() * 3 + 1);
for (let j = 0; j < numItems; j++) {
items[strTime].push({
name: 'Item for ' + strTime + ' #' + j,
height: Math.max(50, Math.floor(Math.random() * 150)),
day: strTime
});
}
}
}
const newItems: AgendaSchedule = {};
Object.keys(items).forEach(key => {
newItems[key] = items[key];
});
this.setState({
items: newItems
});
}, 1000);
}
The entire code snip can be found here: https://gist.github.com/jonasgroendahl/f5e938cdf0a77c2e1509ded22630ba7d
Currently I know this part of the code generates an item for everyday. I'm looking to change this up but I'm not sure what happening line by line. If anyone can please break this down and explain it to me would be great. Thanks.

OfflineAudioContext processing takes increasingly longer in Safari

I am processing an audio buffer with an OfflineAudioContext with the following node layout:
[AudioBufferSourceNode] -> [AnalyserNode] -> [OfflineAudioContext]
This works very good on Chrome (106.0.5249.119) but on Safari 16 (17614.1.25.9.10, 17614) each time I run the analysis takes longer and longer. Both running on macOS.
What's curious is that I must quit Safari to "reset" the processing time.
I guess there's a memory leak?
Is there anything that I'm doing wrong in the JavaScript code that would cause Safari to not garbage collect?
async function processFrequencyData(
audioBuffer,
options
) {
const {
fps,
numberOfSamples,
maxDecibels,
minDecibels,
smoothingTimeConstant,
} = options;
const frameFrequencies = [];
const oc = new OfflineAudioContext({
length: audioBuffer.length,
sampleRate: audioBuffer.sampleRate,
numberOfChannels: audioBuffer.numberOfChannels,
});
const lengthInMillis = 1000 * (audioBuffer.length / audioBuffer.sampleRate);
const source = new AudioBufferSourceNode(oc);
source.buffer = audioBuffer;
const az = new AnalyserNode(oc, {
fftSize: numberOfSamples * 2,
smoothingTimeConstant,
minDecibels,
maxDecibels,
});
source.connect(az).connect(oc.destination);
const msPerFrame = 1000 / fps;
let currentFrame = 0;
function process() {
const frequencies = new Uint8Array(az.frequencyBinCount);
az.getByteFrequencyData(frequencies);
// const times = new number[](az.frequencyBinCount);
// az.getByteTimeDomainData(times);
frameFrequencies[currentFrame] = frequencies;
const nextTime = (currentFrame + 1) * msPerFrame;
if (nextTime < lengthInMillis) {
currentFrame++;
const nextTimeSeconds = (currentFrame * msPerFrame) / 1000;
oc.suspend(nextTimeSeconds).then(process);
}
oc.resume();
}
oc.suspend(0).then(process);
source.start(0);
await oc.startRendering();
return frameFrequencies;
}
const buttonsDiv = document.createElement('div');
document.body.appendChild(buttonsDiv);
const initButton = document.createElement('button');
initButton.onclick = init;
initButton.innerHTML = 'Load audio'
buttonsDiv.appendChild(initButton);
const processButton = document.createElement('button');
processButton.disabled = true;
processButton.innerHTML = 'Process'
buttonsDiv.appendChild(processButton);
const resultElement = document.createElement('pre');
document.body.appendChild(resultElement)
async function init() {
initButton.disabled = true;
resultElement.innerText += 'Loading audio... ';
const audioContext = new AudioContext();
const arrayBuffer = await fetch('https://gist.githubusercontent.com/marcusstenbeck/da36a5fc2eeeba14ae9f984a580db1da/raw/84c53582d3936ac78625a31029022c8fdb734b2a/base64audio.txt').then(r => r.text()).then(fetch).then(r => r.arrayBuffer())
resultElement.innerText += 'finished.';
resultElement.innerText += '\nDecoding audio... ';
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
resultElement.innerText += 'finished.';
processButton.onclick = async () => {
processButton.disabled = true;
resultElement.innerText += '\nStart processing... ';
const t0 = Date.now();
await processFrequencyData(audioBuffer, {
fps: 30,
numberOfSamples: 2 ** 13,
maxDecibels: -25,
minDecibels: -70,
smoothingTimeConstant: 0.2,
});
resultElement.innerText += `finished in ${Date.now() - t0} ms`;
processButton.disabled = false;
};
processButton.disabled = false;
}
I guess this is really a bug in Safari. I'm able to reproduce it by rendering an OfflineAudioContext without any nodes. As soon as I use suspend()/resume() every invocation takes a little longer.
I'm only speculating here but I think it's possible that there is some internal mechanism which tries to prevent the rapid back and forth between the audio thread and the main thread. It almost feels like one of those login forms which takes a bit longer to validate the password every time you try.
Anyway I think you can avoid using suspend()/resume() for your particular use case. It should be possible to create an OfflineAudioContext for each of the slices instead. In order to get the same effect you would only render the particular slice with each OfflineAudioContext.
const currentTime = 0;
while (currentTime < duration) {
const offlineAudioContext = new OfflineAudioContext({
length: LENGTH_OF_ONE_SLICE,
sampleRate
});
const audioBufferSourceNode = new AudioBufferSourceNode(
offlineAudioContext,
{
buffer
}
);
const analyserNode = new AnalyserNode(offlineAudioContext);
audioBufferSourceNode.start(0, currentTime);
audioBufferSourceNode
.connect(analyserNode)
.connect(offlineAudioContext.destination);
await offlineAudioContext.startRendering();
const frequencies = new Uint8Array(analyserNode.frequencyBinCount);
analyserNode.getByteFrequencyData(frequencies);
// do something with the frequencies ...
currentTime += LENGTH_OF_ONE_SLICE * sampleRate;
}
I think the only thing missing would be the smoothing since each of those slices will have it's own AnalyserNode.

How could I change the value of this.buttonState in this scenary?

I'm having issues in this process . First is that I have a button in disabled state(true) and I need to change that value to false when the video is uploaded . I have this scenary and I think I got a windows object inside the changing method . Any idea, help please . I'm getting undefined value for the variable.
data: () => ({
buttonState: true} }),
changeBehavior() {
let self
(function () {
const input = document.getElementById('uploader')
self = this
console.log(this)
const changing = ({ target: { files } }) => {
if (input.files.length > 0) {
// self.buttonState = false
const video = document.getElementById('output-video')
video.src = URL.createObjectURL(files[0])
}
}
input.addEventListener('change', changing)
})()
const au = document.getElementById('output-video')
au.onloadedmetadata = () => {
const hidden = document.getElementById('hiddenSlider')
hidden.removeAttribute('hidden')
const muteHidden = document.getElementById('muteHidden')
muteHidden.removeAttribute('hidden')
self = this
self.range = [0, au.duration]
this.max = au.duration
const secNum = parseInt(au.duration, 10)
let hours = Math.floor(secNum / 3600)
let minutes = Math.floor((secNum - (hours * 3600)) / 60)
let seconds = secNum - (hours * 3600) - (minutes * 60)
if (hours < 10) {
hours = '0' + hours
}
if (minutes < 10) {
minutes = '0' + minutes
}
if (seconds < 10) {
seconds = '0' + seconds
}
document.getElementById('renderizado').innerHTML =
hours + ':' + minutes + ':' + seconds
}
},
<v-btn
id="run"
class="accent-3 blue ml-15"
dark
#click="$refs.inputUpload.click()"
>
<input
v-show="false"
id="uploader"
ref="inputUpload"
accept=".mkv,video/*"
type="file"
#click="changeBehavior"
>
Select to Upload Video
</v-btn>
<v-btn
id="doTrimming"
block
class="accent-3 blue mt-5"
dark
:disabled="buttonState"
#click="cutIt"
>
Trim Video Now
</v-btn>
Where you define self you need to assign this to it then.
changeBehavior() {
const self = this;
const callback = function() {
// now you can access the vue instance when in another functions scope
self.buttonState = true;
}
}

How to find difference between time in moment.js in React Native

How can I find difference time in React Native (I'm using moment):
Like:
let end = endTime; // 10:10:05
let start = startTime; // 10:10:03
moment.utc(moment(end," hh:mm:ss").diff(moment(start," hh:mm:ss"))).format("mm:ss")
//expected output: 00:00:02
You would need to use moment.duration
function timeRemaining (start, end) {
// get unix seconds
const began = moment(start).unix();
const stopped = moment(end).unix();
// find difference between unix seconds
const difference = stopped - began;
// apply to moment.duration
const duration = moment.duration(difference, 'seconds');
// then format the duration
const h = duration.hours().toString();
const m = duration.minutes().toString().padStart(2, '0');
const s = duration.seconds().toString().padStart(2, '0');
return `${h}:${m}:${s}`;
}

Changing the date in Countdown

How can I change the date from my countdown?
I know it is working but can't find the place to change the date!
I'm a newby, sorry for asking!
(function($) {
$.fn.countdown = function(options, callback) {
//custom 'this' selector
thisEl = $(this);
//array of custom settings
var settings = {
'date': null,
'format': null
};
//append the settings array to options
if(options) {
$.extend(settings, options);
}
//main countdown function
function countdown_proc() {
eventDate = Date.parse(settings['date']) / 1000;
currentDate = Math.floor($.now() / 1000);
if(eventDate <= currentDate) {
callback.call(this);
clearInterval(interval);
}
seconds = eventDate - currentDate;
days = Math.floor(seconds / (60 * 60 * 24)); //calculate the number of days
seconds -= days * 60 * 60 * 24; //update the seconds variable with no. of days removed
hours = Math.floor(seconds / (60 * 60));
seconds -= hours * 60 * 60; //update the seconds variable with no. of hours removed
minutes = Math.floor(seconds / 60);
seconds -= minutes * 60; //update the seconds variable with no. of minutes removed
//conditional Ss
if (days == 1) { thisEl.find(".timeRefDays").text("day"); } else { thisEl.find(".timeRefDays").text("days"); }
if (hours == 1) { thisEl.find(".timeRefHours").text("hour"); } else { thisEl.find(".timeRefHours").text("hours"); }
if (minutes == 1) { thisEl.find(".timeRefMinutes").text("minute"); } else { thisEl.find(".timeRefMinutes").text("minutes"); }
if (seconds == 1) { thisEl.find(".timeRefSeconds").text("second"); } else { thisEl.find(".timeRefSeconds").text("seconds"); }
//logic for the two_digits ON setting
if(settings['format'] == "on") {
days = (String(days).length >= 2) ? days : "0" + days;
hours = (String(hours).length >= 2) ? hours : "0" + hours;
minutes = (String(minutes).length >= 2) ? minutes : "0" + minutes;
seconds = (String(seconds).length >= 2) ? seconds : "0" + seconds;
}
//update the countdown's html values.
if(!isNaN(eventDate)) {
thisEl.find(".days").text(days);
thisEl.find(".hours").text(hours);
thisEl.find(".minutes").text(minutes);
thisEl.find(".seconds").text(seconds);
} else {
alert("Invalid date. Here's an example: 12 Tuesday 2012 17:30:00");
clearInterval(interval);
}
}
//run the function
countdown_proc();
//loop the function
interval = setInterval(countdown_proc, 1000);
}
}) (jQuery);
Look for a separate code, or add these lines. Change function/variable/date accordingly
/** Countdown Timer **/
$(document).ready(function() {
"use strict";
$("#countdown").countdown({
date: "20 sep 2020 12:00:00", /** Enter new date here **/
format: "on"
},
function() {
// callback function
});
});
What you provided looks to be the function (the engine) and the code you're looking for calls this. I think you'll find what you are looking for is a line that says something like:
$.fn.countdown({
'date': 'PLACE DATE HERE',
'format': null
}, function(){
//Some code here
);
The values may be slightly different but it'll be something like that. When you call that function, you provide the date to work off of.