In the list of loading previous pages, a loading works very well when dealing with web pages...
But when loading a video iframe .mp4
the loading stays always active, it doesn't disappear unlike loading a website.
For example, when clicking on test5, which is the loading of a video, the pre-loading remains active and does not disappear
This is the code :) or in jsfiddle
function ocultarLoad(){
$('.loading').fadeOut(100);
}
$(document).ready(function(){
var vid = $('#myvid');
//default video source
$(vid).attr("src", $("a.link:first").attr("href"));
// addClass playing to first video link
$("a.link:first").addClass("playing");
$("a.link").on("click" , function (event) {
// prevent link default
event.preventDefault();
$('.loading').fadeIn(200);
// change video source
$(vid).attr("src", $(this).attr("href"));
// remouve class playing from unplayed video href
$(".vids a").removeClass("playing");
// add class playing to video href
$(this).addClass("playing");
// add class paused to give the play/pause button the right look
$('.btnPlay').addClass('paused');
// play the video
vid[0].play();
});
//VIDEO EVENTS
//video canplay event
vid.on('canplay', function() {
$('.loading').fadeOut(100);
});
//video waiting for more data event
vid.on('waiting', function() {
$('.loading').fadeIn(200);
});
//end
});
.container * {
margin: 0;
padding: 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-transition: 0.5s;
-o-transition: 0.5s;
transition: 0.5s;
}
.container *:after , .container *:before {
margin: 0;
padding: 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
h2.title {
font-size: 24px;
color: #fff;
font-weight: bold;
font-family: tahoma;
text-align: center;
padding: 2em;
display: block;
margin: auto;
background-color: #A97A7A;
}
.container {
width: 960px;
background: #010101;
margin: auto;
position: relative;
height: 460px;
}
.vidcontainer {
width: 75%;
height: 100%;
float: right;
position: relative;
overflow: hidden;
}
video {
width: 100%;
height: 405px;
color: #fff;
text-align: center;
font-size: 20px;
}
.videolist {
float: right;
width: 25%;
background-color: rgb(76, 76, 76);
height: 100%;
position: relative;
}
.vids {
margin: 5px;
background-color: #292626;
max-height: 450px;
min-height: 450px;
border: 1px solid #616060;
overflow-y: scroll;
list-style: none;
direction: rtl;
}
.vids::-webkit-scrollbar {
width: 5px;
background-color: #8A8A8A;
border: 1px solid #AFACAC;
}
.vids::-webkit-scrollbar-thumb {
background-color: #FF8D00;
border-radius: 5px;
}
.vids::-webkit-scrollbar-thumb:hover{
background-color:#fff;
}
.vids::-webkit-scrollbar-thumb:active{
background-color:#ccc;
}
.vids a {
text-decoration: none;
color: #fff;
font-size: 16px;
display: block;
border-bottom: 1px solid #616060;
padding: 8px 5px;
margin: 5px;
}
/*--- controllers ---*/
.controllers {
position: absolute;
bottom: 0;
height: 50px;
background-color: #fff;
width: 100%;
}
.controllers button {
border: 1px solid #E7E7E7;
background-color: #FFFFFF;
color: #777;
height: 40px;
width: 40px;
border-radius: 50%;
margin: 5px;
box-shadow: 1px 1px 3px #4C4C4C;
outline: none;
font-size: 18px;
display: inline-block;
float: left;
}
.controllers button:focus {
box-shadow: 1px 0px 7px #4C4C4C;
border-color: #ff8d00;
color: #ff8d00;
background-color: #4C4C4C;
}
.btnPlay:after {
content: "\f04b";
font-family: 'FontAwesome';
}
.paused:after {
content: "\f04c";
}
.sound:after {
content: "\f027";
font-family: 'FontAwesome';
}
.sound2:after {
content: "\f028";
}
.muted:after {
content: "\f026";
}
.btnFS:after {
content: "\f065";
font-family: 'FontAwesome';
}
.ads {
height: 350px;
width: 350px;
position: absolute;
background-color: #777;
top: 27.5px;
right: 40px;
z-index: 11;
}
.bigplay {
height: 150px;
width: 150px;
position: absolute;
top: 127.5px;
left: 85px;
z-index: 11;
color: #fff;
font-size: 150px;
line-height: 150px;
text-align: center;
cursor: pointer;
text-shadow: 0px 0px 15px #ff8d00;
}
.closeme {
height: 32px;
width: 32px;
background-color: #fff;
top: -10px;
right: -10px;
border: 1px solid #ff8d00;
display: block;
position: absolute;
border-radius: 50%;
text-align: center;
line-height: 30px!important;
color: #ff8d00;
font-size: 25px!important;
}
.playing {
background-color: #999;
border: 1px solid #ff8d00!important;
-webkit-transition: 0s;
-o-transition: 0s;
transition: 0s;
}
.playing:after {
content: "\f01d";
font-family: 'FontAwesome';
color: #ff8d00;
float: left;
}
/* PROGRESS BAR CSS */
.topControl {
position: absolute;
display: block;
width: 100%;
bottom: 50px;
background-color: #fff;
z-index: 1;
}
/* Progress bar */
.progress {
width: 100%;
height: 5px;
position: relative;
float: left;
cursor: pointer;
background: #999;
}
.progress span {
height: 100%;
position: absolute;
top: 0;
left: 0;
display: block;
}
.timeBar{
z-index:10;
width:0;
background: #ff8d00;
}
.bufferBar{
z-index:5;
width:0;
background: #eee;
}
/* time and duration */
.time{
width:12%;
float:right;
text-align:center;
font-size:11px;
line-height:12px;
right: -12%;
opacity: 0;
position: absolute;
}
.topControl:hover .time {
right: 0;
opacity: 1;
}
.topControl:hover .progress {
width: 88%;
height: 12px;
}
/* VOLUME BAR CSS */
/* volume bar */
.volume {
position: relative;
cursor: pointer;
width: 70px;
height: 10px;
float: left;
margin-top: 20px;
margin-right: 15px;
background-color: #999;
}
.volumeBar{
display: block;
height: 100%;
position: absolute;
top: 0;
left: 0;
background-color: #ff8d00;
z-index: 10;
}
.loading {
width: 100%;
background-color: rgba(255,141,0,0.5);
height: 405px;
position: absolute;
top: 0;
}
i.fa.fa-spinner.fa-spin {
height: 60px;
width: 60px;
font-size: 60px;
color: #fff;
text-shadow: 0px 0px 8px #000;
top: 172.5px;
left: 330px;
position: absolute;
}
.disabled {
pointer-events: none;
cursor: not-allowed;
background-color: #C2C2C2!important;
}
ul.speedcnt {
display: none;
position: absolute;
right: 30px;
bottom: 60px;
background-color: #fff;
border-radius: 5px;
list-style: none;
-webkit-transition: 0s;
-o-transition: 0s;
transition: 0s;
}
ul.speedcnt li {
text-align: center;
font-family: 'verdana', tahoma , serif;
font-size: 13px;
padding: 5px 20px;
cursor: pointer;
display: block;
border-bottom: 1px solid #ccc;
}
ul.speedcnt li:last-child {
border-bottom: none;
}
ul.speedcnt li.selected {
background-color: rgba(255, 141, 0, 0.6);
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<div class="container">
<div class="vidcontainer">
<iframe id="myvid" onload="ocultarLoad();" >
Your browser does not support the video tag.
</iframe>
<div class="loading">
<i class="fa fa-spinner fa-spin"></i>
</div>
</div>
<div class="videolist">
<nav class="vids">
<a class="link" href="https://en.wikipedia.org/wiki/Main_Page">test1</a>
<a class="link" href="http://legacy.datatables.net/usage/columns">test2</a>
<a class="link" href="https://stackoverflow.com/">test3</a>
<a class="link" href="http://futbolworldcup.com/">test4</a>
<a class="link" href="https://www.quirksmode.org/html5/videos/big_buck_bunny.mp4">test5</a>
<a class="link" href="http://www.html5videoplayer.net/videos/toystory.mp4">test6</a>
<a class="link" href="http://download.wavetlan.com/SVV/Media/HTTP/H264/Other_Media/H264_test8_voiceclip_mp4_480x320.mp4">test7</a>
<a class="link" href="http://download.wavetlan.com/SVV/Media/HTTP/MP4/ConvertedFiles/Media-Convert/Unsupported/dw11222.mp4">test8</a>
<a class="link" href="http://download.wavetlan.com/SVV/Media/HTTP/MP4/ConvertedFiles/Media-Convert/Unsupported/test7.mp4">tsest9</a>
</nav>
</div>
</div>
How can I fix this error?
Note: I am using Chrome the current version, the preloading only disappears on websites and not on multimedia such as videos.
Problemas de diseño
Primero que nada, hay unos pocos errores de diseño. Hay que eliminar la función
ocultarLoad
, porque no es necesario, ya que elfadeout
está envid.on
.En consecuencia, eliminarlo en la etiqueta
iframe
.Queda así:
Además hay que eliminar esta línea, que tira error. El video se reproduce automáticamente al cargar el
iframe
, por lo que no tiene sentido agregarlo.También quitar la clase
.btnPlay
, ya que no existe ningún botón que tenga esa clase.Quitarlo desde el CSS
También desde el JavaScript:
Problema principal
Una vez resueltos estos problemas de diseño, hay que tener en cuenta una cosa:
El jQuery espera poder reproducir (can play) el video, cuando es una página HTML. El atributo es solo compatible con
<audio>
y<video>
, pero no con un<iframe>
.Si es un video, hay que usar
canplay
, de lo contrario hay que usarload
.Como jQuery no puede entrar en el contenido de un
iframe
, no es posible detectar si lo que hay dentro es un video o una página. Entonces, si la URL termina en.mp4
, podemos crear un<video>
, de lo contrario, creamos un<iframe>
, entonces hago un RegExp^.+\.mp4$
.Dentro de
<video>
se le agrega un<source>
con el atributosrc
, que es la URL, ytype
, que en este caso esvideo/mp4
.Para ordenar mejor las cosas, hice una función llamada
insertar_contenido
, que dependiendo de la URL, hace alguna de las dos cosas, o insertar unvideo
, o uniframe
. También encapsulé las funciones delfadeIn
yfadeOut
, ahora son llamadasmostrar
yocultar
.En algunas ocasiones, la extensión puede no coincidir con el formato del video, puede terminar en
.mp4
, y al final tener diferentes códecsogv
ompeg H264
. Para esto, altype
se le puede asignarvideo/mp4; codecs=avc1
, pero hay que saberlo de antemano.Para saber el códec es necesario descargar el video y abrirlo con un programa que pueda leer el codec, puede ser un reproductor de videos. Por ejemplo, el VLC puede verlo solo mientras lo está reproduciendo, en Tools -> Información del códec.
Código
En los únicos casos donde puede fallar es cuando la página a cargar no existe o el navegador no puede cargarlo en el
iframe
, o que puede cargarlo pero no lo carga por seguridad. Es recomendable no mezclar contenido HTTP en páginas HTTPS. En lo posible siempre usar HTTPS, que es contenido seguro certificado en SSL.Antes que nada hay que resaltar que dicho «problema» ocurre en Chrome principalmente, en Firefox y Edge funciona «bien» (se oculta el loading una vez carga el archivo), y en Safari 12 parece funcionar de forma intermitente según las pruebas que hice.
El mensaje que aparece en la consola al cargar los videos en Chrome es:
Lo cual traduce aproximadamente:
En otras palabras, Chrome esperaba un documento (HTML probablemente) pero le entregamos un video.
El problema parece estar en que Chrome no lanza ningún evento en un iframe cuando su contenido no es un documento HTML. Esto significa en nuestro caso que el evento onLoad nunca es lanzado y nunca se oculta el div que contiene el loading.
Este parece ser el típico problema que no es un bug sino un feature de Chrome lo que estamos analizando.
Como casi siempre, hay varias formas de solucionar este problema, una consiste en agregar en el handler de clic que ya tienes, un código de JavaScript que detecte que estás en Chrome (y en Safari tal vez en caso que sea relevante), y revisar después de X tiempo si hay algo de contenido en el iframe (con lo cual asumiríamos que la carga del video fue exitosa) y ocultar el loading: