We have a dynamic element on the page that in certain situations will have a video (Vimeo). The jQuery code checks if the element excists and adds video itself and the play on hover.
This works (tested on Chrome & Firefox) after you have interacted with the website. Before you interact, you run into the autoplay policies, a good thing in my opinion, and the console will tell you the action is not allowed.
You might get around this with muting the video. But the contents are about a person explaining something. So without the sound it loses a lot of its value. So would like to keep that in.
As said, these policies are a good thing in my opinion, so I do not want a way around it or a way to trick it into playing anyway. I would like to add some other functionality when the site is in this 'state'(?). Add a button or some other incentive to interact with the site and play the video. But if not in this 'state' I would like to keep the play on hover.
Is there a way I can detect this state?
I see another question, almost the same issue: Is there an event to detect when user interacted with a page?
But the solutions there are not answers to the problem, like trying it with an interval until it works... creative, but not something I'm looking for.
Here is in short what I have now. And what is missing.
...video settings...
if ($('#vidcontainer').length) {
var videoPlayer = new Vimeo.Player('vidcontainer', options);
...
if state is 'allow hover' {
...
$("#vidcontainer").mouseover(function () {
videoPlayer.play();
}).mouseout(function () {
videoPlayer.pause();
});
...
} else if state is 'not allowd hover' {
... do something else ...
}
...
}
Related
Right now I have a very basic HTML5 Audio player that play from webradio.
I use a old iPad to play the music but also to show some information from a webpage. The problem is that is happen sometime the wifi and the old iPad does not like to stay connect so it disconnect and reconnect and then the player stop play the webradio. I need somehow a script that notice in real time or every 1 min if the radio is not running and restart the player for me. I guess I can use Javascript but have search a Little and not find any good idea and it also have to work in Chrome. It looks that some javaScript does not work in specific webbrowser
Basically, your <audio> element will dispatch an error event. Just listen for that and then retry. You could also listen to the progress event to see when it starts receiving again and then call play from there. It'd be something roughly like this:
const audio = getAudioElement();
audio.addEventListener('error', () => { playing = false; /* handle error */ });
audio.addEventListener('progress', () => {
if (!playing) {
audio.play();
playing = true;
}
});
I'm currently using VideoJS in a Rails application (where there is a video player on every page) to display videos and I'm encountering a very strange problem:
The player works perfectly fine on the first page I visit but if I play the video and visit another page, the video from the first page keeps playing in the background even though the page isn't open anymore (you can hear the audio) and the video on the page you visited doesn't initialize properly (options aren't applied which means the video can't be played because controls are an option) and the console reads VIDEOJS: WARN: Player "player" is already initialised. Options will not be applied.
How to I get VideoJS to unload itself when the user leaves the page and why does it keep playing in the first place, the HTML5 video player didn't do that before.
Is the best way around this to get VideoJS to reload itself manually on page load? If so, how can that be done?
Note: If I navigate to any other page within the website the videos continue to not initialize, but if I reload the page, any page, the video on said page works again.
Note 2: Turns out that the onbeforeunload javascript event doesn't even fire if I click a link to another page, it only fires if you're going to a whole different website, so I can't even use that to .dispose() VideoJS on page unload.
Note 3: .reset() doesn't seem to be working either.
You can check to see if the player already exists and unload it, then reload it.
I was actually able to figure out a fairly simple and elegant solution:
if (player) {player.dispose()} else {var player}
player = videojs('player', {
//options
});
First it checks to see if the player exists. If it does, it destroys the VideoJS instance. If it doesn't, it creates the variable. Then it initializes the player.
By Referring this issue : https://github.com/videojs/video.js/issues/2904
We can re-write the above solution to something like this:
const playerId = 'video-player';
const videoOptions = {
controls: true,
sources: [{
src: 'test-file.mp4',
type: 'video/mp4',
}]
};
let player;
let players = videojs.players;
const imaOptions = { adTagUrl };
if (players && Object.keys(players).length) {
player = players[playerId];
player.dispose();
}
player = videojs(playerId,videoOptions);
player.ima(imaOptions);
I found this one to be the solution:
var oldPlayer = document.getElementById('my-player');
videojs(oldPlayer).dispose();
it's in the docs actually
I have a fun little button on a website I am developing here:
http://dev.lapiazzaonline.com/merrick.php
When you click on the takeout menu button on desktop and chrome inspector iPhone simulator it works great.... with a nice little delay.
Now on iOS, nothing happens. I think it might have to do with the hover state issue, but more think my JS is messed up.
this is the js in the behavior.js file
// cool buttons
(function() {
var removeSuccess;
removeSuccess = function() {
return $('.button').removeClass('success');
};
$(document).ready(function() {
return $('.button').click(function(e) {
e.preventDefault();
var goTo = this.getAttribute("href");
$(this).addClass('success');
setTimeout(removeSuccess, 1500);
setTimeout(function(){
window.open(goTo);
},1500);
});
});
}).call(this);
Any ideas?
Thanks,
-Muhu
Your issue here is the use of window.open. You can read more about this here and other similar issues if you search. Unfortunately, there are multiple reports that jQuery trigger will not work either. So, what I would do is just use something like Modernizr, or if you just want to figure out which browser it is, this is a nice tool, and then when you're on iOS or a browser with similar blocking functionality, run a different function that doesn't prevent the default, and opens the link normally.
I noticed that if I have a gmail tab open with conversation view on/off, and then I open another tab and change the conversation view setting, my original tab stays in the conversation view state it started in such as when doing new searches etc. and the new tab uses the setting I just changed it to.
This led me to think there might be some JavaScript bookmarklet / favelet / "scriptlet" that could easily let us change the setting for a given gmail tab temporarily without having to go into the settings.
Does anyone know of this already in existence or is anyone able to create it? My thought would be to capture a load of gmail with it on and with it off and do a diff / winmerge on the two to see what's different and take it from there, but I'm hoping someone's already created it =).
I'll look into the gmail js and make a bookmarklet :P
Edit: seems the js is obfuscated A lot, copying the function from the original js is gonna be hard...
I'll check what the html changes are between both views and write a js function myself to apply those changes.
I went and instead made it a bit different, I wrote some js that does actually the thing that you would do yourself(it simulates going to settings and changing them).
I made a jsfiddle with a link that can be dragged into the bookmarks bar:
https://jsfiddle.net/randomengineer/0nc4hajp/4/
The bookmarklet code:
javascript:
window.location.hash = 'settings/general';
a = () => document.querySelector('tbody tr:nth-child(13) input:not(:checked)');
b = setInterval(() => {
if(a() != null) {
clearInterval(b);
a().click();
document.querySelector('[guidedhelpid=save_changes_button]').click();
}
}, 5);
Saved settings are just to reload the JS code in the way you prefer, so you are correct it can be made easy to change. seahorsepip did a good one on it, if you need a custom grease script to install to your chrome i would be glad to help.
Love the solution by seahorsepip. I combined it with the "Shortcut Manager" Chrome extension (http://www.makeuseof.com/tag/shortcut-manager-assign-hotkeys-to-various-browser-actions-chrome/) and now I can toggle with a keyboard shortcut!
New solution for 2019 (see Bookmarklet in JavaScript to toggle Gmail conversation view).
This will toggle the current state On/Off and Save:
window.location.href = "https://mail.google.com"+window.location.pathname+"#settings/general";
setTimeout(function() {
convTogs = document.getElementsByName("bx_vmb");
if (convTogs[0].checked) convTogs[1].click();
else convTogs[0].click();
document.querySelector("[guidedhelpid=save_changes_button]").click();
}, 2000);
(Thanks, #Zenoo!)
Note: If you have multiple Gmail accounts open (like me) this will work in your current window (unlike https://mail.google.com/mail/u/0/#settings/general which will go to your default account)
I’d like to place interaction controls above a youtube iframe video, and I got it working quite OK by just adding wmode=opaque as arguments and then position the elements absolute above the iframe.
My problem is that on mobile safari - the controls work fine first, but when I return from the fullscreen video, they are all disabled. It works fine on desktop though.
The HTML is basically:
<iframe src="http://www.youtube.com/embed/[ID]?wmode=opaque"></iframe>
<button id="btn">Click me</button>
And then the button is positioned absolute above the iframe.
For a demo, please visit this fiddle using your mobile safari: http://jsfiddle.net/SwGH5/embedded/result/
You’ll see that the button yields an alert when clicked. Now, play the video and click "done". Then try to click the button again...
If the movie was embedded using the <video> tag I could listen for a fullscreen-end event and do something, but now I’m stuck...
Here’s the fiddle: http://jsfiddle.net/SwGH5
So I played around with the iframe API a bit and found a solution. It's kind of hacky... but not really. When a user clicks on the video to play it, the document.activeElement becomes the iframe. When the user clicks the "done" button, the document.activeElement === document.body. So when the video starts playing, we periodically check to see if the active element returns to the body. At that point, the only solution I found was to redraw the iframe. In the example, I destroy() the video and recreate it using the iframe API. I also tried cloning the iframe and replacing it with success (I left that code there so you could see it):
http://jsfiddle.net/ryanwheale/SwGH5/105/
It's not the best solution, but it works. Also, to give an explanation of what [I think] is happening - iOS hijacks any video content (Safari or Chrome) and plays it using the native video player. Any type of OS functionality like this takes place "over" the browser if you will - higher than any z-index... completely outside the browser. When the user clicks "done" the native player kind of zooms out as if it is re-implanting itself on the page. My best guess is that the native player is still hanging out "over" the browser... thus making anything underneath it inaccessible. The fact that the button appears to be on top is just an anomaly... for lack of better description.
EDIT: Ryan Wheale's solution is a better workaround to this problem and will work in most cases.
From Apple’s documentation:
On iOS-based devices with small screens—such as iPhone and iPod touch—video always plays in fullscreen mode, so the canvas cannot be superimposed on playing video. On iOS-based devices with larger screens, such as iPad, you can superimpose canvas graphics on playing video, just as you can on the desktop.
Same goes for a "played video" either. This article clearly states it's not possible.
Workaround:
You could detach and re-attach the iframe element on webkitfullscreenchange. But it won't work for a foreign iframe. Browser will not allow you to manipulate iframe DOM bec. of the cross-domain policy. And even if it did, you could only hide the video overlay to reach your button anyway.
So, the only solution is watching for YT.PlayerState.ENDED state via YouTube iFrame API and then destroying and re-creating the player. But don't worry it plays smooth.
window.onYouTubeIframeAPIReady = function () {
var video = {
player: null,
create: function () {
// first destroy if we already have the player
if (video.player) { video.player.destroy(); }
// create the player
video.player = new YT.Player('ytp', {
videoId: '9u_hp7zPir0',
width: '620',
height: '290',
events: {
'onStateChange': video.onStateChange
}
});
},
onStateChange: function (event) {
// YT.PlayerState.ENDED » exiting full screen
if (event.data === 0) { video.create(); }
}
};
video.create();
};
Here is the working fiddle.
If you can't get it to work with the regular iframe, you might want to consider using mediaelement.js - which can wrap the Youtube API in a HTML5 Media API wrapper. That works fine on safari on ios - try the Youtube example at mediaelementjs.com.
All you need to do is to add the mejs js/css and put your youtube video as source in your video tag, here is some example markup taken from mediaelementjs.com:
<script src="jquery.js"></script>
<script src="mediaelement-and-player.min.js"></script>
<link rel="stylesheet" href="mediaelementplayer.css" />
<video width="640" height="360" id="player1" preload="none">
<source type="video/youtube" src="http://www.youtube.com/watch?v=nOEw9iiopwI" />
</video>
Then start the player like so:
jQuery(document).ready(function($) {
$('#player1').mediaelementplayer();
});
If you want to add your button ontop of the mejs player it will work fine, just set the z-index high enough. If you want a regular play button you could also consider styling the existing one that comes with mejs.
By the comments from #CullenJ's answer, possibly it might be due to some problem in iOS device browsers not triggering the click event on iframe elements. In that case, you would have to change from:
document.getElementById('btn').onclick = function() {
alert('clicked');
}
To something like this (as answered by #smnh):
$('#btn').on('click tap touchstart', function() {
alert('clicked');
});