Shinobi/web/assets/js/bs5.timeline.js

769 lines
29 KiB
JavaScript

$(document).ready(function(){
var theWindow = $('#tab-timeline')
var timeStripVideoCanvas = $('#timeline-video-canvas');
var timeStripEl = $('#timeline-bottom-strip');
var timeStripControls = $('#timeline-controls');
var timeStripInfo = $('#timeline-info');
var timeStripPreBuffers = $('#timeline-pre-buffers');
var timeStripObjectSearchInput = $('#timeline-video-object-search');
var dateSelector = $('#timeline-date-selector');
var sideMenuList = $(`#side-menu-link-timeline ul`)
var playToggles = timeStripControls.find('[timeline-action="playpause"]')
var speedButtons = timeStripControls.find('[timeline-action="speed"]')
var gridSizeButtons = timeStripControls.find('[timeline-action="gridSize"]')
var autoGridSizerButtons = timeStripControls.find('[timeline-action="autoGridSizer"]')
var currentTimeLabel = timeStripInfo.find('.current-time')
var timelineActionButtons = timeStripControls.find('[timeline-action]')
var timelineSpeed = 1;
var timelineGridSizing = `md-6`;
var timeStripVis = null;
var timeStripVisTick = null;
var timeStripVisItems = null;
var timeStripCurrentStart = null;
var timeStripCurrentEnd = null;
var timeStripVisTickMovementInterval = null;
var timeStripVisTickMovementIntervalSecond = null;
var timeStripHollowClickQueue = {}
var timeStripTickPosition = new Date()
var timeStripPreBuffersEls = {}
var timeStripItemColors = {}
var timeStripAutoGridSizer = false
var timeStripListOfQueries = []
var timeStripSelectedMonitors = []
var timeStripAutoScrollTimeout = null;
var timeStripAutoScrollPositionStart = null;
var timeStripAutoScrollPositionEnd = null;
var timeStripAutoScrollAmount = null;
var loadedVideosOnTimeStrip = []
var loadedVideosOnCanvas = {}
var loadedVideoElsOnCanvas = {}
var loadedVideoElsOnCanvasNextVideoTimeout = {}
var loadedVideoEndingTimeouts = {}
var isPlaying = false
var earliestStart = null
var latestEnd = null
var timeChanging = false
var dateRangeChanging = false
function setLoadingMask(turnOn){
if(turnOn){
if(theWindow.find('.loading-mask').length === 0){
var html = `<div class="loading-mask"><i class="fa fa-spinner fa-pulse fa-5x"></i></div>`
theWindow.prepend(html)
}
}else{
theWindow.find('.loading-mask').remove()
}
}
function addVideoBeforeAndAfter(videos) {
videos.sort((a, b) => {
if (a.mid === b.mid) {
return new Date(a.time) - new Date(b.time);
}
return a.mid.localeCompare(b.mid);
});
for (let i = 0; i < videos.length; i++) {
if (i > 0 && videos[i].mid === videos[i - 1].mid) {
videos[i].videoBefore = videos[i - 1];
} else {
videos[i].videoBefore = null;
}
if (i < videos.length - 1 && videos[i].mid === videos[i + 1].mid) {
videos[i].videoAfter = videos[i + 1];
} else {
videos[i].videoAfter = null;
}
}
return videos;
}
function findGapsInSearchRanges(timeRanges, range) {
timeRanges.sort((a, b) => a[0] - b[0]);
let gaps = [];
let currentEnd = new Date(range[0]);
for (let i = 0; i < timeRanges.length; i++) {
let [start, end] = timeRanges[i];
if (start > currentEnd) {
gaps.push([currentEnd, start]);
}
if (end > currentEnd) {
currentEnd = end;
}
}
if (currentEnd < range[1]) {
gaps.push([currentEnd, range[1]]);
}
return gaps;
}
async function getVideosInGaps(gaps,monitorIds){
var searchQuery = timeStripObjectSearchInput.val()
var videos = []
async function loopOnGaps(monitorId){
for (let i = 0; i < gaps.length; i++) {
var range = gaps[i]
videos.push(...(await getVideos({
monitorId,
startDate: range[0],
endDate: range[1],
searchQuery,
// archived: false,
// customVideoSet: wantCloudVideo ? 'cloudVideos' : null,
},null,true)).videos);
}
}
if(monitorIds && monitorIds.length > 0){
for (let ii = 0; ii < monitorIds.length; ii++) {
var monitorId = monitorIds[ii]
await loopOnGaps(monitorId)
}
}else{
await loopOnGaps('')
}
return videos;
}
async function getVideosByTimeStripRange(addOrOverWrite){
// timeStripSelectedMonitors = selected monitors
var currentVideosLength = parseInt(loadedVideosOnTimeStrip.length)
var stripDate = getTimestripDate()
var startDate = stripDate.start
var endDate = stripDate.end
var gaps = findGapsInSearchRanges(timeStripListOfQueries, [startDate,endDate])
// console.error([startDate,endDate])
// console.log('range : ',JSON.stringify([startDate,endDate]))
// console.log('timeRanges : ',JSON.stringify(timeStripListOfQueries))
// console.log('gaps : ',JSON.stringify(gaps))
if(gaps.length > 0){
setLoadingMask(true)
timeStripListOfQueries.push(...gaps)
var videos = await getVideosInGaps(gaps,timeStripSelectedMonitors)
videos = addVideoBeforeAndAfter(videos)
loadedVideosOnTimeStrip.push(...videos)
if(currentVideosLength !== loadedVideosOnTimeStrip.length)resetTimelineItems(loadedVideosOnTimeStrip);
setLoadingMask(false)
}
return loadedVideosOnTimeStrip
}
function selectVideosForCanvas(time, videos){
var selectedVideosByMonitorId = {}
$.each(loadedMonitors,function(n,monitor){
selectedVideosByMonitorId[monitor.mid] = null
})
var filteredVideos = videos.filter(video => {
var startTime = new Date(video.time);
var endTime = new Date(video.end);
return time >= startTime && time <= endTime;
});
$.each(filteredVideos,function(n,video){
selectedVideosByMonitorId[video.mid] = video;
})
return selectedVideosByMonitorId;
}
function drawVideosToCanvas(selectedVideosByMonitorId){
var html = ''
var preBufferHtml = ''
$.each(loadedMonitors,function(monitorId,monitor){
var itemColor = stringToColor(monitorId)
timeStripItemColors[monitorId] = itemColor
html += `<div class="timeline-video col-${timelineGridSizing} p-0 m-0 no-video" data-mid="${monitorId}" data-ke="${monitor.ke}" style="background-color:${itemColor}"></div>`
preBufferHtml += `<div class="timeline-video-buffer" data-mid="${monitorId}" data-ke="${monitor.ke}"></div>`
})
timeStripVideoCanvas.html(html)
timeStripPreBuffers.html(preBufferHtml)
$.each(selectedVideosByMonitorId,function(monitorId,video){
if(!video)return;
setVideoInCanvas(video)
})
}
function destroyTimeline(){
try{
timeStripVis.destroy()
}catch(err){
// console.log(err)
}
}
function formatVideosForTimeline(videos){
var i = 0;
var formattedVideos = (videos || []).map((item) => {
var blockColor = timeStripItemColors[item.mid];
++i;
return {
id: i,
content: ``,
style: `background-color: ${blockColor};border-color: ${blockColor}`,
start: item.time,
end: item.end,
group: 1
}
});
return formattedVideos
}
function createTimelineItems(){
var items = new vis.DataSet([]);
var groups = new vis.DataSet([
{id: 1, content: ''}
]);
timeStripVisItems = items
return {
items,
groups,
}
}
function resetTimelineItems(videos){
var newVideos = formatVideosForTimeline(videos)
timeStripVisItems.clear();
timeStripVisItems.add(newVideos);
}
async function resetTimeline(clickTime){
await getAndDrawVideosToTimeline(clickTime,true)
setTickDate(clickTime)
setTimeLabel(clickTime)
setTimeOfCanvasVideos(clickTime)
setHollowClickQueue()
}
function createTimeline(){
var timeChangingTimeout = null
var dateNow = new Date()
var hour = 1000 * 60 * 60
var startTimeForLoad = new Date(dateNow.getTime() - (hour * 24 + hour))
destroyTimeline()
var {
items,
groups,
} = createTimelineItems()
// make chart
timeStripVis = new vis.Timeline(timeStripEl[0], items, groups, {
showCurrentTime: false,
stack: false,
start: timeStripCurrentStart || startTimeForLoad,
end: timeStripCurrentEnd || dateNow,
});
// make tick
timeStripVisTick = timeStripVis.addCustomTime(dateNow, `${lang.Time}`);
timeStripVis.on('click', async function(properties) {
var currentlyPlaying = !!isPlaying;
timeStripPlay(true)
if(!timeChanging){
var clickTime = properties.time;
await resetTimeline(clickTime)
}
if(currentlyPlaying){
setTimeout(() => {
timeStripPlay()
},500)
}
});
timeStripVis.on('rangechange', function(properties){
timeChanging = true
})
timeStripVis.on('rangechanged', function(properties){
clearTimeout(timeChangingTimeout)
timeStripCurrentStart = properties.start;
timeStripCurrentEnd = properties.end;
timeStripAutoScrollPositionStart = getTimeBetween(timeStripCurrentStart,timeStripCurrentEnd,10);
timeStripAutoScrollPositionEnd = getTimeBetween(timeStripCurrentStart,timeStripCurrentEnd,90);
timeStripAutoScrollAmount = getTimelineScrollAmount(timeStripCurrentStart,timeStripCurrentEnd);
if(dateRangeChanging)return;
timeChangingTimeout = setTimeout(function(){
var clickTime = properties.time;
resetDateRangePicker()
setTimeout(() => {
timeChanging = false
getAndDrawVideosToTimeline(clickTime)
},500)
},300)
})
setTimeout(function(){
timeStripEl.find('.vis-timeline').resize()
},2000)
}
function getTimelineScrollAmount(start,end){
var startTime = start.getTime()
var endTime = end.getTime()
var difference = (endTime - startTime) / 1000;
var minute = 60
var hour = 60 * 60
var day = 60 * 60 * 24
// returns hours
if(difference <= 60){
return 0.1
}else if(difference > minute && difference <= hour){
return 0.3
}else if(difference > hour && difference < day){
return 0.6
}else if(difference >= day){
return 10
}
}
function scrollTimeline(addHours){
if(timeStripAutoScrollTimeout)return;
timeStripAutoScrollTimeout = setTimeout(() => {
delete(timeStripAutoScrollTimeout)
timeStripAutoScrollTimeout = null
},2000)
var stripTime = getTimestripDate()
var timeToAdd = addHours * 1000 * 60 * 60
var start = new Date(stripTime.start.getTime() + timeToAdd)
var end = new Date(stripTime.end.getTime() + timeToAdd)
setTimestripDate(start,end)
}
function setTickDate(newDate){
if(isPlaying){
if(newDate >= timeStripAutoScrollPositionEnd){
scrollTimeline(timeStripAutoScrollAmount)
}else if(newDate >= new Date()){
timeStripPlay(true)
}
}
timeStripTickPosition = new Date(newDate)
return timeStripVis.setCustomTime(newDate, timeStripVisTick);
}
function setTimeLabel(newDate){
return currentTimeLabel.text(`${timeAgo(newDate)}, ${getDayOfWeek(newDate)}, ${formattedTime(newDate)}`)
}
function getTickDate() {
return timeStripTickPosition;
}
function getTimestripDate() {
var visibleWindow = timeStripVis.getWindow();
var start = visibleWindow.start;
var end = visibleWindow.end;
return {
start,
end
};
}
function setTimestripDate(newStart, newEnd) {
return timeStripVis.setWindow(newStart, newEnd);
}
function selectAndDrawVideosToCanvas(theTime,redrawVideos){
var selectedVideosForTime = selectVideosForCanvas(theTime,loadedVideosOnTimeStrip)
loadedVideosOnCanvas = selectedVideosForTime;
if(redrawVideos){
drawVideosToCanvas(selectedVideosForTime)
}
}
async function getAndDrawVideosToTimeline(theTime,redrawVideos){
await getVideosByTimeStripRange()
selectAndDrawVideosToCanvas(theTime,redrawVideos)
}
function getVideoContainerInCanvas(video){
return timeStripVideoCanvas.find(`[data-mid="${video.mid}"][data-ke="${video.ke}"]`)
}
function getVideoElInCanvas(video){
return getVideoContainerInCanvas(video).find('video')[0]
}
function getVideoContainerPreBufferEl(video){
return timeStripPreBuffers.find(`[data-mid="${video.mid}"][data-ke="${video.ke}"]`)
}
function getWaitTimeUntilNextVideo(endTimeOfFirstVideo,startTimeOfNextVideo){
return (new Date(startTimeOfNextVideo).getTime() - new Date(endTimeOfFirstVideo).getTime()) / timelineSpeed
}
function clearVideoInCanvas(oldVideo){
var monitorId = oldVideo.mid
loadedVideosOnCanvas[monitorId] = null
loadedVideoElsOnCanvas[monitorId] = null
clearTimeout(loadedVideoEndingTimeouts[monitorId])
var container = getVideoContainerInCanvas(oldVideo).addClass('no-video')
var videoEl = container.find('video')
videoEl.attr('src','')
try{
videoEl[0].pause()
}catch(err){
console.log(err)
}
container.empty()
timeStripAutoGridResize()
}
function setVideoInCanvas(newVideo){
var monitorId = newVideo.mid
getVideoContainerInCanvas(newVideo).removeClass('no-video').html(`<video muted src="${newVideo.href}"></video>`)
var vidEl = getVideoElInCanvas(newVideo)
vidEl.playbackRate = timelineSpeed
if(isPlaying)playVideo(vidEl)
loadedVideoElsOnCanvas[monitorId] = vidEl
loadedVideosOnCanvas[monitorId] = newVideo
timeStripPreBuffersEls[monitorId] = getVideoContainerPreBufferEl(newVideo)
queueNextVideo(newVideo)
timeStripAutoGridResize()
}
function setTimeOfCanvasVideos(newTime){
$.each(loadedVideosOnCanvas,function(n,video){
if(!video)return;
var monitorId = video.mid
var timeAfterStart = (newTime - new Date(video.time)) / 1000;
var videoEl = loadedVideoElsOnCanvas[monitorId]
videoEl.currentTime = timeAfterStart
// playVideo(videoEl)
// pauseVideo(videoEl)
})
}
function queueNextVideo(video){
if(!video)return;
var monitorId = video.mid
var videoEl = loadedVideoElsOnCanvas[monitorId]
var videoAfter = video.videoAfter
var endingTimeout = null;
var alreadyDone = false;
function currentVideoIsOver(){
if(alreadyDone)return;
alreadyDone = true;
clearVideoInCanvas(video)
if(videoAfter){
var waitTimeTimeTillNext = getWaitTimeUntilNextVideo(video.end,videoAfter.time)
// console.log('End of Video',video)
// console.log('Video After',videoAfter)
// console.log('Starting in ',waitTimeTimeTillNext / 1000, 'seconds')
loadedVideoElsOnCanvasNextVideoTimeout[monitorId] = setTimeout(() => {
setVideoInCanvas(videoAfter)
},waitTimeTimeTillNext)
// }else{
// console.log('End of Timeline for Monitor',loadedMonitors[monitorId].name)
}
}
videoEl.onerror = function(err){
err.preventDefault()
console.error(`video error`)
console.error(err)
}
videoEl.ontimeupdate = function(){
if(videoEl.currentTime >= videoEl.duration){
clearTimeout(loadedVideoEndingTimeouts[monitorId])
currentVideoIsOver()
}else if(isPlaying){
var theTime = getTickDate()
var waitTimeTimeTillNext = getWaitTimeUntilNextVideo(theTime,video.end)
clearTimeout(loadedVideoEndingTimeouts[monitorId])
loadedVideoEndingTimeouts[monitorId] = setTimeout(() => {
currentVideoIsOver()
},waitTimeTimeTillNext)
}
}
// pre-buffer it
timeStripPreBuffersEls[monitorId].html(videoAfter ? `<video preload="auto" muted src="${videoAfter.href}"></video>` : '')
}
function findVideoAfterTime(time, monitorId) {
let inputTime = new Date(time);
let matchingVideos = loadedVideosOnTimeStrip.filter(video => {
let videoTime = new Date(video.time);
return video.mid === monitorId && videoTime > inputTime;
});
matchingVideos.sort((a, b) => new Date(a.time) - new Date(b.time));
return matchingVideos.length > 0 ? matchingVideos[0] : null;
}
function setHollowClickQueue(){
$.each(loadedVideosOnCanvas,function(monitorId,video){
if(!video){
// console.log(`Add Hollow Action`, loadedMonitors[monitorId].name)
var tickTime = getTickDate()
var foundVideo = findVideoAfterTime(tickTime,monitorId)
clearTimeout(loadedVideoElsOnCanvasNextVideoTimeout[monitorId])
if(foundVideo){
var waitTimeTimeTillNext = getWaitTimeUntilNextVideo(tickTime,foundVideo.time)
// console.log('Found Video',foundVideo)
// console.log('Video Starts in ',waitTimeTimeTillNext / 1000, 'seconds after Play')
timeStripHollowClickQueue[monitorId] = () => {
// console.log('Hollow Start Point for',loadedMonitors[monitorId].name)
loadedVideoElsOnCanvasNextVideoTimeout[monitorId] = setTimeout(() => {
// console.log('Hollow Replace')
setVideoInCanvas(foundVideo)
},waitTimeTimeTillNext)
}
}else{
// console.log('End of Timeline for Monitor',loadedMonitors[monitorId].name)
timeStripHollowClickQueue[monitorId] = () => {}
}
}else{
timeStripHollowClickQueue[monitorId] = () => {}
}
})
}
function runHollowClickQueues(){
$.each(timeStripHollowClickQueue,function(monitorId,theAction){
theAction()
})
}
function getAllActiveVideosInSlots(){
return timeStripVideoCanvas.find('video')
}
function playVideo(videoEl){
try{
videoEl.playbackRate = timelineSpeed
videoEl.play()
}catch(err){
console.log(err)
}
}
function pauseVideo(videoEl){
try{
videoEl.pause()
}catch(err){
console.log(err)
}
}
function playAllVideos(){
getAllActiveVideosInSlots().each(function(n,video){
playVideo(video)
})
}
function pauseAllVideos(){
getAllActiveVideosInSlots().each(function(n,video){
pauseVideo(video)
})
}
function setPlayToggleUI(icon){
playToggles.html(`<i class="fa fa-${icon}"></i>`)
}
function timeStripPlay(forcePause){
if(!forcePause && !isPlaying){
isPlaying = true
var currentDate = getTickDate().getTime();
var msSpeed = 50
var addition = 0
var newTime
runHollowClickQueues()
playAllVideos()
timeStripVisTickMovementInterval = setInterval(function() {
addition += (msSpeed * timelineSpeed);
newTime = new Date(currentDate + addition)
setTickDate(newTime);
// setTimeOfCanvasVideos(newTime)
}, msSpeed)
timeStripVisTickMovementIntervalSecond = setInterval(function() {
setTimeLabel(newTime);
}, 1000)
setPlayToggleUI(`pause-circle-o`)
}else{
isPlaying = false
pauseAllVideos()
clearInterval(timeStripVisTickMovementInterval)
clearInterval(timeStripVisTickMovementIntervalSecond)
$.each(loadedVideoElsOnCanvasNextVideoTimeout,function(n,timeout){
clearTimeout(timeout)
})
$.each(loadedVideoEndingTimeouts,function(n,timeout){
clearTimeout(timeout)
})
setPlayToggleUI(`play-circle-o`)
}
}
// function downloadPlayingVideo(video){
// if(video.currentSrc){
// var filename = getFilenameFromUrl(video.currentSrc)
// downloadFile(video.currentSrc,filename)
// }
// }
function getLoadedVideosOnCanvas(){
return Object.values(loadedVideosOnCanvas).filter(item => !!item)
}
function downloadAllPlayingVideos(){
zipVideosAndDownloadWithConfirm(getLoadedVideosOnCanvas())
}
async function jumpTimeline(amountInMs,direction){
timeStripPlay(true)
var tickTime = getTickDate().getTime()
var newTime = 0;
if(direction === 'right'){
newTime = tickTime + amountInMs
}else{
newTime = tickTime - amountInMs
}
newTime = new Date(newTime)
await resetTimeline(newTime)
if(tickTime <= timeStripAutoScrollPositionStart){
scrollTimeline(-timeStripAutoScrollAmount)
}else if(tickTime >= timeStripAutoScrollPositionEnd){
scrollTimeline(timeStripAutoScrollAmount)
}
}
function adjustTimelineSpeed(newSpeed){
var currentlyPlaying = !!isPlaying;
if(currentlyPlaying)timeStripPlay(true);
timelineSpeed = newSpeed + 0
setHollowClickQueue()
if(currentlyPlaying)timeStripPlay();
}
function adjustTimelineGridSize(newCol){
timelineGridSizing = `${newCol}`
var containerEls = timeStripVideoCanvas.find('.timeline-video')
containerEls.removeClass (function (index, className) {
return (className.match (/(^|\s)col-\S+/g) || []).join(' ');
}).addClass(`col-${newCol}`)
gridSizeButtons.removeClass('btn-success')
timeStripControls.find(`[timeline-action="gridSize"][size="${newCol}"]`).addClass('btn-success')
}
async function refreshTimeline(){
var currentlyPlaying = !!isPlaying;
timeStripPlay(true)
timeStripListOfQueries = []
loadedVideosOnTimeStrip = []
createTimeline()
await resetTimeline(getTickDate())
if(currentlyPlaying)timeStripPlay();
}
function timeStripAutoGridSizerToggle(){
if(timeStripAutoGridSizer){
timeStripAutoGridSizer = false
autoGridSizerButtons.removeClass('btn-success')
dashboardOptions('timeStripAutoGridSizer','2')
}else{
timeStripAutoGridSizer = true
autoGridSizerButtons.addClass('btn-success')
timeStripAutoGridResize()
dashboardOptions('timeStripAutoGridSizer','1')
}
}
function timeStripAutoGridResize(){
if(!timeStripAutoGridSizer)return;
var numberOfBlocks = getLoadedVideosOnCanvas().length
if(numberOfBlocks <= 1){
adjustTimelineGridSize(`md-12`)
}else if(numberOfBlocks >= 2 && numberOfBlocks < 5){
adjustTimelineGridSize(`md-6`)
}else if(numberOfBlocks >= 5){
adjustTimelineGridSize(`md-4`)
}
}
function resetDateRangePicker(){
var stripDate = getTimestripDate()
var startDate = stripDate.start
var endDate = stripDate.end
var picker = dateSelector.data('daterangepicker')
picker.setStartDate(startDate);
picker.setEndDate(endDate);
}
function drawFoundCamerasSubMenu(){
var tags = getListOfTagsFromMonitors()
var allFound = [
{
attributes: `timeline-menu-action="selectMonitorGroup" tag=""`,
class: `cursor-pointer`,
color: 'green',
label: lang['All Monitors'],
}
]
$.each(tags,function(tag,monitors){
allFound.push({
attributes: `timeline-menu-action="selectMonitorGroup" tag="${tag}"`,
class: `cursor-pointer`,
color: 'blue',
label: tag,
})
})
if(allFound.length === 1){
allFound.push({
attributes: ``,
class: ``,
color: ' d-none',
label: `<small class="mt-1">${lang.addTagText}</small>`,
})
}
var html = buildSubMenuItems(allFound)
sideMenuList.html(html)
}
sideMenuList.on('click','[timeline-menu-action]',function(){
var el = $(this)
var type = el.attr('timeline-menu-action')
switch(type){
case'selectMonitorGroup':
var tag = el.attr('tag')
if(!tag){
timeStripSelectedMonitors = []
}else{
var tags = getListOfTagsFromMonitors()
var monitorIds = tags[tag]
timeStripSelectedMonitors = [...monitorIds];
}
refreshTimeline()
break;
}
})
timelineActionButtons.click(function(){
var el = $(this)
var type = el.attr('timeline-action')
switch(type){
case'playpause':
timeStripPlay()
break;
case'downloadAll':
if(featureIsActivated(true)){
downloadAllPlayingVideos()
}
break;
case'jumpLeft':
jumpTimeline(5000,'left')
break;
case'jumpRight':
jumpTimeline(5000,'right')
break;
case'speed':
var speed = parseInt(el.attr('speed'))
if(featureIsActivated(true)){
adjustTimelineSpeed(speed)
speedButtons.removeClass('btn-success')
el.addClass('btn-success')
}
break;
case'gridSize':
var size = el.attr('size')
adjustTimelineGridSize(size)
break;
case'refresh':
refreshTimeline()
break;
case'autoGridSizer':
timeStripAutoGridSizerToggle()
break;
}
})
timeStripObjectSearchInput.change(function(){
refreshTimeline()
})
timeStripVideoCanvas.on('dblclick','.timeline-video',function(){
var monitorId = $(this).attr('data-mid')
openVideosTableView(monitorId)
})
addOnTabOpen('timeline', async function () {
createTimeline()
await resetTimeline(getTickDate())
drawFoundCamerasSubMenu()
})
addOnTabReopen('timeline', function () {
drawFoundCamerasSubMenu()
})
addOnTabAway('timeline', function () {
timeStripPlay(true)
})
loadDateRangePicker(dateSelector,{
timePicker: true,
timePicker24Hour: true,
timePickerSeconds: true,
timePickerIncrement: 30,
autoApply: true,
buttonClasses: 'hidden',
drops: 'up',
maxDate: new Date(),
onChange: function(start, end, label) {
if(!timeChanging){
setLoadingMask(true)
dateRangeChanging = true
setTimestripDate(start, end)
var newTickPosition = getTimeBetween(start,end,50);
setTickDate(newTickPosition)
setTimeout(() => {
dateRangeChanging = false
refreshTimeline()
},2000)
}
}
})
var currentOptions = dashboardOptions()
if(isChromiumBased){
[ 7, 10 ].forEach((speed) => {
timeStripControls.find(`[timeline-action="speed"][speed="${speed}"]`).remove()
});
}
if(!currentOptions.timeStripAutoGridSizer || currentOptions.timeStripAutoGridSizer === '1'){
timeStripAutoGridSizerToggle()
}
})