How to hide only Picture in Picture (PiP) control from safari - javascript

I need to hide only one video control from safari browser which is Picture in Picture (PiP). Is there is any solution for that ?
Can we hide this using HTML5?

disablePictureInPicture attribute can be used for that now
<video disablepictureinpicture controlslist="nodownload"></video>
details here:
https://wicg.github.io/picture-in-picture/#disable-pip

There doesn't seem to be any official way to do it...
Currently in Safari it's all or nothing (with controls=false).
The shadow-targetting pseudo elements selectors doesn't seem to work on this browser, unlike on Blink browsers, and even though I found references of an ::-webkit-media-controls-picture-in-picture-button on the Internet.
So for today, the only solution is to disable all the default controls of your video element and to build you own controls.
If you wish, you can make it conditional though:
if(typeof vidElem.webkitSupportsPresentationMode === 'function' &&
vidElem.webkitSupportsPresentationMode('picture-in-picture') ) {
vidElem.controls = false;
buildCustomControls(vidElem);
}
For the future, there might a controlsList attribute, which drafts specs currently only handles nodownload, nofullscreen and noremoteplayback, but I can't see why a nopicture-in-picture couldn't make its way there, if this attribute (mainly motivated by Blink browsers, once again) ever gets out of the drafts.

Related

Click handler on <video> conflicts with Firefox's native behaviour

I've added a video to my site using the default HTML5 video player. The code is like this:
<video width="100%" height="100%" controls>
<source src="http://media.sublimevideo.net/v/midnight-sun-short-edit-360p.mp4" type="video/mp4">
</video>
I wanted to make it so a click on the video stops or starts the video. So I added this:
onclick="this.paused?this.play():this.pause();"
And all good. Until Firefox 35 adds this very function to the player. So now you can only play the video by right clicking and selecting play - an ordinary click would first make the video play via the native behaviour, and then immediately pause it via my click handler. Terrible. So I thought up a JavaScript function something like this:
function startstop() {
if ( FirefoxVersionNumber > 34 ) {
// do nothing
} else {
// start or stop video
}
}
The bit I'm stuck on is how to check the browser version? All the ones I tried returned that Firefox version number was 5... which I think comes from the Netscape part.
You need to prevent the default behaviour of the click event, in much the same way that you would prevent the default behaviour of a form submit if you were handling it yourself with JavaScript.
Event.preventDefault is the tool for the job.
Just do
video.addEventListener('click', function (event) {
event.preventDefault(); // Prevent the default behaviour in Firefox
// Then toggle the video ourselves
if (this.paused) {
this.play();
}
else {
this.pause();
}
});
Here's a Fiddle that works both in Chrome (which has no built-in click-to-toggle behaviour on videos) and in Firefox (which, at least in recent versions, does): http://jsfiddle.net/LjLgkk71/
As an aside, as a general rule you should forget browser sniffing until you've truly and utterly exhausted all other avenues (with the exception of using it to work around specific known quirks and bugs in old browsers, relating to behaviour that has since been fixed or standardised). The idea you expressed in the question, of simply not applying your click handler on certain browser versions, was misguided; you have no way of knowing (and nor do I) what other browsers share or will one day share Firefox's behaviour. If you'd taken your approach, it's almost inevitable that it would come back to bite you either when one of the major browsers followed Firefox's example or when one of your users tried to use your site on a Nintendo DS or something.
There may very likely be better ways to handle this, but here's one that I've come up with: I looked through the release notes for Firefox 35, and it looks like one of the changes made in 35 was fixing a bug where a method called .hasAttributes() that, according to spec, is supposed to be located on Element was previously located on Node. So, although it looks odd, you could do something like:
if(typeof InstallTrigger !== 'undefined' &&
typeof Element.prototype.hasAttributes !== 'undefined') {
// is Firefox >= 35
}
This is based on the fact that typeof InstallTrigger !== 'undefined' would identify Firefox as per this answer and we know .hasAttributes moved to Element beginning in version 35. This would be preferable to user agent parsing because unlike the User Agent string it is unlikely to be spoofed in any way.
It's been mentioned in the comments that it seems odd to do a form of browser detection by checking for the presence of an unrelated JavaScript object - but this is a practice that's established and has been used historically to detect versions of a specific browser greater than a certain version: Here's an article that describes commonly used variables that can be used to detect Internet Explorer versions >= a given number.

html5 <video> tag; click anywhere js works everywhere but firefox

Firefox seems to add it’s own ‘click anywhere to play’ behavior, it dims the poster and adds a play button. It works great, but the problem is that no other browsers seem to add that behavior automatically. So, I’ve had to implement a javascript workaround to allow ‘click anywhere to play’ in other browsers. They work great, but now it’s broken in firefox. The way it behaves, it seems like the javascript I put in there is getting a click and making it play, but then ff’s own ‘click anywhere to play’ catches the click too, and pauses it immediately. I can inch along the entire video, 1 or 2 seconds at a time, if keep clicking. As for the specific js workarounds that I've tried, many of the examples from these two threads:
How can I add click-to-play to my HTML5 videos without interfering with native controls?
and
Click the poster image the HTML5 video plays?
I was really hoping for a <video> attribute like click-anywhere="yes", but I think I'm out of luck there. Or, as a solution to my problem, something like the css: moz-click-anywhere:false; to allow the js to handle clicks exclusively.
The only solution I can think of is the browser detection route, but I’m hoping there’s a more elegant solution. If not, so be it, but it was worth asking.

How to make a webpage play a sound

I need to make a sound from a webpage immediately after load (OK/NOT OK signal depending on the case). The page is generated and I can control the content fully.
How do I do this in a modern, cross browser compatible way? I've experienced problems with <audio> tag (maybe browser issues, maybe I'm doing it somehow wrong). Currently I use a small flash player, but as you might guess, it is not a perfect solution.
And yes, the sound is exactly what the user wants, so please no "website with sound is not a good idea" -comments. Generally I would agree, but there are special cases.
Using an audio element works in modern browsers, and for older browsers, you can use an embed fallback (which may or may not work, depending on installed plugins, but if it does not work, there is not much you can do):
<audio src=maamme.mp3 controls autoplay>
<embed src=maamme.mp3>
</audio>
This creates visible controls at the place where you put this element. You can modify those controls to some extent or hide them. If you want to control more exactly when the presentation starts, you can dynamically add the element into the document instead of having it statically there. If old browsers are not very relevant, you could alternatively use an audio element without autoplay and use the HTMLMediaElement interface to start the presentation, do things when it has ended, etc.
If you wish to control the audio yourself, you can do it programatically through javascript.
window.onload = function(){
var snd = new Audio("sound/mysound.wav");
snd.play();
}
This should load the audio file and play it automatically once the page has loaded. It should be noted however that iOS limits any audio being played like this, without a user interaction (e.g. a click) because it forces the user to use up bandwidth and takes control away from them. Android, and other devices may or may not allow autoplaying audio, but all latest web browsers on desktop allow it (Chrome, FF, IE9+, Safari)

Feature Detection for setDragImage of HTML5 Drag and Drop

Is there a way to do feature detection for setDragImage of HTML5 Drag and Drop (in JavaScript or Dart)?
I do the general HTML5 Drag and Drop feature detection with the following (from guide to detecting everything):
return 'draggable' in document.createElement('span');
This will return true for Chrome, Firefox, etc., and IE10. It will return false for IE9.
Now, the problem is with IE10: While it supports most of HTML5 Drag and Drop, setDragImage is not supported and I need to provide a polyfill just for setDragImage. But I couldn't figure out a way how to detect this.
This solution assumes general D&D support has already been checked.
JavaScript (tested in IE, Firefox, Opera and Chrome):
function test() {
var testVar = window.DataTransfer || window.Clipboard; // Clipboard is for Chrome
if("setDragImage" in testVar.prototype) {
window.alert("supported");
} else {
window.alert("not supported");
}
}
Dart:
I didn't find a way to do this with "native" Dart code, so js-interop is the way to go.
You can use the setDragImage-IE polyfill:
https://github.com/MihaiValentin/setDragImage-IE
This is how it actually works (from the README):
I noticed that if you make a change to the element's style (adding a
class that changes appearance) inside the dragstart event and then
removing it immediately in a setTimeout, Internet Explorer will make
a bitmap copy of the modified element and will use it for dragging.
So, what this library actually does is implement the setDragImage
method that changes the target's element style by adding a class that
includes the image that you want to appear while dragging, and then
removes it. In this way, the browser displays the temporary style of
the element as the drag image.
The feature detection mentioned in the previous answer fails in Opera 12 -- because it claims support for setDragImage, it just doesn't work. The Dart libraries that have been linked to also fail entirely in Opera 12, throwing multiple errors to the console.
It's actually not possible to polyfill a ghost image -- even if you create a document element and position it in the right place, you can't get rid of the default one without setDragImage.
The only solution I know of is to filter-out Opera 12 and all versions of IE (up to and including IE11) and treat them as legacy browsers, which have to be catered for with traditional mouse-event scripting. Since the direct feature testing fails, I would recommend an indirect object test (i.e. use an object test to detect those specific browsers):
var hasNativeDraggable = (element.draggable && !(document.uniqueID || window.opera));

JavaScript - shuffling audio

I am creating a webpage that uses JavaScript to shuffle a series of audio file questions and their matching drag-and-drop answers. I have successfully implemented this using the native HTML5 audio tags but also have a fallback section for IE 7/8 since these browsers cannot read the audio tag. This fallback section uses conditional comments around object and param tags as demonstrated at the end of this article here.
It works in that it does shuffle in IE, but breaks in that it displays the ugly Media Player-style controls that I had specifically hidden, as this activity uses "play sound" buttons instead of audio player controls.
If anyone needs to see specific parts of code, just let me know.
Many thanks in advance!
Two thoughts (sorry, I'm on a mac at the moment so testing in IE isn't a great option):
I see the parameters where you're trying to hide the controls, but have you also tried applying css to the object tag or to a container wrapped around it? It might be as simple as giving a wrapper div a style of display: none or visibility: hidden.
This isn't a direct answer to your question, but have you investigated any plugins such as SoundManager 2? It uses HTML5 audio with a Flash fallback; I've used it before and had success. Obviously it requires Flash on older browsers, but if that's not an issue it could be easier than trying to figure out how to hide the controls.
It's a nice little page by the way. Good luck!
To address your second question/comment: using an object/embed tag means that you're relying on the browser/OS deciding on what plugin it will use to play audio. Some Googling turns up issues with IE and quicktime, and one possible solution:
Jan 2009 Microsoft update breaks mp3 sound objects in IE7
IE issues with quicktime
Hope it helps. SoundManager 2 might be worth trying if you keep hitting walls, just be aware that using SM2 will mandate that users with older browsers have Flash installed and unblocked.
I’ve managed to out the second issue with the audio in IE – for the shuffle script to work with the audio in IE, you have to call the shuffle BEFORE the audio code – in my case I moved all the conditional comments below the .shuffle(); stuff and it works no worries!

Categories