jPlayer: Get current volume - javascript

I am trying to save the current volume of my jPlayer to a cookie. This is my code.
//Save the jPlayer volume when it changes.
$("#startpage_jplayer").bind($.jPlayer.event.volumechange, function(event){
//Cache the volume value.
var new_volume = event.jPlayer.options.volume;
//Store the volume in a cookie.
$.cookie('jp_volume', new_volume, { expires: 7, path: '/'});
});
Each time the volume changes I get that there is no options property.
I suppose they moved the property but it's really hard to find the new one.
Thank you for your time.
Console Screenshot

I used some deprecated event detection methods before and when I updated my code, my server did not clear the cache after flushing it 5 times.
The code is fine, thus problem solved !

Related

How can I remove local storage after one hour?

My data is object
I save it use local storage javascript like this :
localStorage.setItem('storedData', JSON.stringify(data))
I just want to keep that data for 1 hour. So if it's been more than 1 hour then the data will be removed
I know to remove data like this :
localStorage.removeItem("storedData")
But how can I set it to auto delete after 1 hour?
You can't.
When do items in HTML5 local storage expire?
The only thing you can do is set the delete statement in a timeout of 1 hour. This requires the user to stay on your page or the timeout won't be executed.
You can also set an expiration field. When the user revisits your site, check the expiration and delete the storage on next visit as the first thing you do.
Add the following code in your App.js file, then the localStorage will be cleared for every 1 hour
var hours = 1; // to clear the localStorage after 1 hour
// (if someone want to clear after 8hrs simply change hours=8)
var now = new Date().getTime();
var setupTime = localStorage.getItem('setupTime');
if (setupTime == null) {
localStorage.setItem('setupTime', now)
} else {
if(now-setupTime > hours*60*60*1000) {
localStorage.clear()
localStorage.setItem('setupTime', now);
}
}
use setInterval, with setting/pushing expiration key in your local data,
check code below.
var myHour = new Date();
myHour.setHours(myDate.getHours() + 1); //one hour from now
data.push(myHour);
localStorage.setItem('storedData', JSON.stringify(data))
function checkExpiration (){
//check if past expiration date
var values = JSON.parse(localStorage.getItem('storedData'));
//check "my hour" index here
if (values[1] < new Date()) {
localStorage.removeItem("storedData")
}
}
function myFunction() {
var myinterval = 15*60*1000; // 15 min interval
setInterval(function(){ checkExpiration(); }, myinterval );
}
myFunction();
You can't use setTimeout().Since you can't guarantee your code is going to be running on the browser in 1 hours. But you can set a timestamp and while returning back just check with Timestamp and clear the storage out based on expiry condition.
Use cookies instead
Cookies.set('foo_bar', 1, { expires: 1/24 })
Alternatively you can use IndexedDB in WebWorkers. What it basically means is you can create a parallel to your main thread JavaScript program, like this
var worker = new Worker('worker.js');
The advantage is when it finishes its work, and you don't have a reference to it, it gets cleaned up automatically.
However, since I'm not fully sure about the above, here is The worker's lifetime from Living Standard
Workers communicate with other workers and with browsing contexts
through message channels and their MessagePort objects.
Each WorkerGlobalScope object worker global scope has a list of the
worker's ports, which consists of all the MessagePort objects that are
entangled with another port and that have one (but only one) port
owned by worker global scope. This list includes the implicit
MessagePort in the case of dedicated workers.
Given an environment settings object o when creating or obtaining a
worker, the relevant owner to add depends on the type of global object
specified by o. If o specifies a global object that is a
WorkerGlobalScope object (i.e., if we are creating a nested dedicated
worker), then the relevant owner is that global object. Otherwise, o
specifies a global object that is a Window object, and the relevant
owner is the responsible document specified by o.
A worker is said to be a permissible worker if its WorkerGlobalScope's
owner set is not empty or:
its owner set has been empty for no more than a short implementation-defined timeout value,
its WorkerGlobalScope object is a SharedWorkerGlobalScope object (i.e., the worker is a shared worker), and
the user agent has a browsing context whose Document object is not completely loaded.
Another advantage is you can terminate a worker, like this
worker.terminate();
Also, it is worth mentioning
IndexedDB has built-in support for schema versions and upgrading via
its IDBOpenDBRequest.onupgradeneeded() method; however, you still
need to write your upgrade code in such a way that it can handle the
user coming from a previous version (including a version with a bug).
This works for a SPA where the browser window doesn't reload on page renders:
Set an expiresIn field in your local storage.
On window reload check to see if current time >= expiresIn
if true clear localStorage items else carry on
You can also do this check whenever your business logic requires it.
Just add the check in your app to check if the variable exists and then do a check on it. Put a unix timestamp on the variable, and compare that the next time the user visits your site.
I think setTimeout() method will do the trick.
UPDATED:
While setting the value to localStorage also set the time of recording the data.
// Store the data with time
const EXPIRE_TIME = 1000*60*60;
localStorage.setItem('storedData', JSON.stringify({
time: new Date(),
data: "your some data"
}));
// start the time out
setTimeout(function() {
localStorage.removeItem('storedData');
}, EXPIRE_TIME); // after an hour it will delete the data
Now the problem is if user leave the site. And setTimeout will not work. So when user next time visit the site you have to bootstrap the setTimeout again.
// On page load
$(document).ready(function() {
let userData = JSON.parse(localStorage.getItem('storedData')) || {};
let diff = new Date() - new Date(userData.time || new Date());
let timeout = Math.max(EXPIRE_TIME - diff, 0);
setTimeout(function() {
localStorage.removeItem('storedData');
}, timeout);
})

Video length of playlist items Webchimera.js Player

Environment
NW.js v0.12.3
io.js v1.2.0
32 bits
Windows 8
Webchimera.js (player)
The following code works but I'm left wondering if it's the best approach. The requirement is to get the length of each video that's in the playlist.
To do that I use the events onPlaying and onPaused.
wjs = require('wcjs-player');
...
chimera_container = new wjs("#chimera_container");
chimera_player = chimera_container.addPlayer({ mute: true, autoplay: false, titleBar: "none" });
chimera_player.onPlaying( OnPlaying ); // Pauses player
chimera_player.onPaused( OnPaused ); // Extracts length information
var OnPlaying = function(){
chimera_player.pause();
};
var OnPaused = function() {
console.log( chimera_player.itemDesc(chimera_player.currentItem()).mrl , chimera_player.length());
if(!chimera_player.next())
chimera_player.clearPlaylist();
};
At first I tried doing all the code in the event onPlaying but the app always crashed with no error. After checking chimera_player.state() it seemed that even after doing chimera_player.pause() the state didn't change while inside the onPlaying event. I figure having state Playing and trying to do chimera_player.next() causes the exception.
This way seems a bit hacky, but I can't think of another one.
My approach was definitely not the best. #RSATom kindly exposed the function libvlc_media_get_duration in the WebChimera.js API.
In order to get the duration all that is needed is:
... after adding playlist...
var vlcPlaylist = chimera_player.vlc.playlist;
for(var i=0, limit=chimera_player.itemCount(); i<limit; ++i ){
var vlcMedia = vlcPlaylist.items[i];
vlcMedia.parse(); // Metadata is not available if not parsed
if(vlcMedia.parsed)
// Access duration via --> vlcMedia.duration
else
logger("ERROR -- parsePlaylist -- " + vlcMedia.mrl );
}
If you are going to try to get duration from files with MPEG format then you are in for a headache. In order to have VLC return duration of MPEG file before playing the video, it is necessary that its Demuxer is set to Avformat demuxer. Problem is you can't do that via the libvlc api. If demuxer is not set, then vlcMedia.duration will always return 0.
There's two options here:
Use ffprobe to access video metadata and forget doing it via libvlc
Play with this posts' original way of getting duration via a combination of play() pause() events.
I've tried find any function in libvlc API allowed get media length without playing it - with no success. So it's very possible there are no way to get media length without playing it.
I was wrong, it's possible (with libvlc_media_get_duration), but it's not exposed in WebChimera.js API yet. I'll add it if you will create issue for it on GitHub.
P.S.: And it will be great if you will create issues on GitHub for discovered crashes...
upd: required API implemented

Tab-to-tab communication using BreezeJS and localStorage

I'm using BreezeJS and storing/restoring data in local storage. That's working great. The problem occurs when the user opens multiple tabs. Changes in each tab clobber each other. Changes should be synchronised between tabs.
NB: BreezeJS will take care of merging changes, I just need to deal with race conditions between tabs.
var stashName = 'stash_everything';
window.setInterval(function () {
var exportData = manager.exportEntities();
window.localStorage.setItem(stashName, exportData);
}, 5000);
addEvent(window, 'storage', function (event) {
if (event.key == stashName) {
var importData = window.localStorage.getItem(stashName);
manager.importEntities(importData);
}
});
I've tried listening to the 'storage' event, but I haven't been able to get it working successfully. I either still clobber changes, or get into an infinite loop.
The crux of the issue is that I'm just saving on a timer; if I only saved after user interaction, then I'd avoid (most) race conditions. There's no 'has the user changed anything since last time I asked you' call in breeze, though, as far as I can tell.
Does anyone have advice on how to approach this?
Hmm this doesn't seem like it is impervious to having problems for many reasons but the main one would be that you still won't prevent concurrent saves from each tab with different data sets. That being said, if you are comfortable with the fact the two caches could be out of sync just use some unique identifier -
Somewhere in your app on load -
var stashName = 'stash-everything-' + new Date().getTime();
window.setInterval(function () {
var exportData = manager.exportEntities();
window.localStorage.setItem(stashName, exportData);
}, 5000);
Now each tab would have a unique set of data to work with.

Get frame numbers in HTML5 Video

I am trying to capture each frame number of the video however it looks like there is no way of achieving it. So I started my own clock to match the frame numbers of the video but they never match and the difference keeps increasing as the video progress.
Please have a look at my bin. http://jsbin.com/dopuvo/4/edit
I have added the frame number to each frame of the video from Adobe After Effect so I have more accurate information of the difference. The Video is running at 29.97fps and the requestAnimationFrame is also set to increase the number at the same rate, however I am not sure where this difference is coming from.
Sometimes they match and sometimes they don't. I also tried doing it offline but I get the same results. Any help.
I found something on github for this. https://github.com/allensarkisyan/VideoFrame
I have implemented it in this fiddle: https://jsfiddle.net/k0y8tp2v/
var currentFrame = $('#currentFrame');
var video = VideoFrame({
id : 'video',
frameRate: 25,
callback : function(frame) {
currentFrame.html(frame);
}
});
$('#play-pause').click(function(){
if(video.video.paused){
video.video.play();
video.listen('frame');
$(this).html('Pause');
}else{
video.video.pause();
video.stopListen();
$(this).html('Play');
}
});
EDIT: updated fiddle to new video so it works again.
EDIT: As pointed out, the video is 25fps, so I updated it, and while I was there removed reliance on jQuery.
Non jQuery version:
https://jsfiddle.net/k0y8tp2v/1/
var currentFrame = document.getElementById('currentFrame');
var video = VideoFrame({
id : 'video',
frameRate: 25,
callback : function(frame) {
currentFrame.innerHTML = frame ;
}
});
document.getElementById('play-pause').addEventListener('click', function(e){
if(video.video.paused){
video.video.play();
video.listen('frame');
e.target.innerHTML = 'Pause';
}else{
video.video.pause();
video.stopListen();
e.target.innerHTML = 'Play';
}
});
The problem is that setTimeout is not really predictable, so you can't be sure that exactly one new frame has been displayed every time your function runs. You need to check the currentTime of the video every time you update your frame display and multiply that by the frame rate.
Here's a working example: http://jsbin.com/xarekice/1/edit It's off by one frame, but it looks like you may have two frames at the beginning marked "000000".
A few things about the video element that you may want to be aware of:
As you seem to have discovered, there's no reliable way to determine the frame rate, so you have to discover it elsewhere and hard-code it. There are some interesting things going on with video metrics, but they're non-standard, not widely supported and, in my experience, completely ineffective at determining the actual frame rate.
The currentTime is not always exactly representative of what's on the screen. Sometimes it's ahead a little bit, especially when seeking (which is why in my JSBin, I don't update the frame while you're seeking).
I believe currentTime updates on a separate thread from the actual video draw, so it kind of works like it's own clock that just keeps going. It's where the video wants to be, not necessarily where it is. So you can get close, but you need to round the results of the frame calculation, and once in a while, you may be off by one frame.
Starting in M83, Chromium has a requestVideoFrameCallback() API, which might solve your issue.
You can use the mediaTime to get a consistent timestamp, as outlined in this Github issue. From there, you could try something like this:
var frameCounter = (time, metadata) => {
let count = metadata.mediaTime * frameRate;
console.log("Got frame: " + Math.round(count));
// Capture code here.
video.requestVideoFrameCallback(frameCounter);
}
video.requestVideoFrameCallback(frameCounter)
This will only fire on new frames, but you may occasionally miss one (which you can detect from a discontinuity in the metadata.presentedFrames count). You might also be slightly late in capturing the frame (usually 16ms, or one call to window.requestAnimationFrame() later than when the video frame is available).
If you're interested in a high level overview of the API, here's a blogpost, or you can take a look at the API's offical github.

How to detect focus when reopening Safari on iPhone?

I have a web-application for iPhone, and I need to trigger a Javascript function when the web page is in focus, in other words, when Safari is open.
What I want to accomplish is to start a timer in some way when the user clicks on a tel-link and starts the call. When the call ends, Safari pops up again, and the timer ends.
Is there any way to do this?
Best Regards
Linus
try this:
if you trigger the link for the call set the actual time in a localStorage-item.
$("#yourButton").click(function() {
var actualTime = new Date().getTime();
window.localStorage.setItem('callStart', actualTime);
})
after that you need to read the Storage after user ends up the call.
You can set this in the document.ready on the opening page.
in $(document).ready(function() {})
// check for the localStorageItem
if (window.localStorage.getItem('callStart')) {
// get it
var timeStart = window.localStorage.getItem('callStart');
var now = new Date().getTime();
/*
Now calculate here the difference now - timeStart
and you will get seconds, minutes or whatever you want
*/
// !!! Dont forget to clear the localStorageItem
window.localStorage.removeItem('callStart');
}
This is what I would try. The Usage of the HTML5-localStorage gives you the possibility to store key/values and data isnt lost if user stops the app or device is automatically locked.
Hope this helps a bit.
ADDED: You even can store JSON as the value in the localStorageItem. So you can set an callID and implement a calling-history for your users.

Categories

Resources