I have a HTML5 video element on my webpage and I want to create a custom timeline control for the video. However, I am having problems when I seek right to the end of the video. When I try to seek backwards, the video does not change (the ticker still moves though). Calling the "play" method does nothing either. The only thing that does seem to work is the "currentTime" and "ended" properties, which are still updated correctly.
Here is the HTML layout of my video and ticker (the "blocks" table has a z-index of 1000 and sits below the ticker, so it does not interfere with it):
<div id="player">
<video width="500">
<source src="Tutorial 1.mp4" type="video/mp4">
</video>
<ul>
<li id="play_pause" title=""><img src="control.png"></img></li>
<li id="volume" title=""><img src="speaker_volume.png"></img></li>
<li id="split" title=""><img src="scissors_plus.png"></img></li>
<li id="merge" title=""><img src="film_minus.png"></img></li>
</ul>
<div id="timecode" class="modtime"><img src="mark_time.png"></img><div></div></div>
</div>
...
<div id="timeline">
<table id="blocks" width="100%" cellspacing="0" cellpadding="0" border="0" class="CRZ">
<tbody>
<tr>
<td style="width: 800px;"></td>
</tr>
</tbody>
</table>
<div id="ticker"></div>
</div>
And here's the CSS for the "ticker" and "timeline" elements:
#timeline {
float: left;
width: 850px;
height: 30px;
background: lightblue;
margin-left: 25px;
border: 1px solid black;
border-radius: 2px;
}
#ticker {
height: inherit;
width: 1px;
background: red;
z-index: 3000;
position: relative;
left: 0px;
cursor: col-resize;
opacity: 1;
}
I made the "ticker" element draggable using Jquery UI, creating an event handler to update the videos "currentTime" property during the drag. The "timecode" element displays the "currentTime" element in MM:SS.SS. This is still functional after seeking to the end.
$("#ticker").draggable({ containment: "parent", axis: "x", cursor: "col-resize", grid: [ 1, 1 ], drag: function( event, ui ) {
$("#stage2 video").prop("currentTime", ((ui.position.left - 1) * $("#stage2 video").prop("duration")) / ($("#timeline").width() - 2));
$("#timecode div").text(sec2smpte($("#stage2 video").prop("currentTime")));
}});
I also scripted the ticker to move when the video is playing (controlled by simply calling the "play" method when a button is clicked). The behaviour is apparent whether the video has been played or not:
$("#stage2 video").on("timeupdate", function() {
$("#ticker").css("left", ($("#timeline").width() * $("#stage2 video").prop("currentTime")) / $("#stage2 video").prop("duration") + "px");
$("#timecode div").text(sec2smpte($("#stage2 video").prop("currentTime")));
});
$("#play_pause").click(function() {
if ($("#play_pause img").attr("src") == "control.png")
{
$("#play_pause img").attr("src", "control_pause.png");
$("#stage2 video").trigger("play");
}
else
{
$("#play_pause img").attr("src", "control.png");
$("#stage2 video").trigger("pause");
}
});
UPDATE: I ran my source video through FFmpeg and that seemed to fix the issue. It seems to be a seeking problem with some .mp4 files. I also noticed that it would exhibit similar behaviour if it tried to seek backwards.
Related
In a single html page there are multiple video tags and all these videos may be played simultaneously. I have build an application where I am capturing video using webrtc and video capture device. These video are not seekable.
So I am calling below code for each of those video tag so that video which are playing can be seekable.
This code works fine if I apply to only one tag but when I apply it for multiple video tag it wont work.
$scope.addListenerVideo = function(videoSrc) {
var videoSrcVar = document.getElementById(videoSrc);
if(videoSrcVar !=null) {
videoSrcVar.addEventListener('loadedmetadata', () => {
if (videoSrcVar !=null && videoSrcVar.duration === Infinity) {
videoSrcVar.currentTime = 1e101;
videoSrcVar.ontimeupdate = function() {
videoSrcVar.currentTime = 0;
videoSrcVar.ontimeupdate = function() {
delete videoSrcVar.ontimeupdate;
};
};
}
});
}
}
html code sample:
<div class="row">
<div class="first-column">
<video width="636" height="380" controls preload="auto" ng-show="actStatus_1" id="demoVideoSrc1" style="border: 1px solid black; margin-top: 10px; margin-left: 10px; "></video>
</div>
<div class="second-column">
<video width="600" height="380" controls preload="auto" ng-show="actStatus_2" id="demoVideoSrc2" style="border: 1px solid black; margin-top: 10px; margin-left: 149px;"></video>
</div>
</div>
Here I switched to mozilla firefox. There is issue with the way video capture in chrome which is not allowing video to be seekable. I don't know whether I was missing something or not. Once I switched to Firefox browser there was no issue with seeking video.
I met very strange behavior on iOS Safari 7+
I'm using flexslider and for some reason it doesn't work when i click on a link and go to the page i use it. If i copy and paste the link in the address bar it works. Also it works on all other popular mobile browsers. Here is js i used to debug the issue:
if (!vertical || fade) {
var $obj = (fade) ? slider : slider.viewport;
var objHeight = slider.slides.eq(slider.animatingTo).height();
console.log($obj.height());
(dur) ? $obj.animate({"height": objHeight}, dur) : $obj.height(objHeight);
if ($obj.height() == 0) { $obj.css("height", objHeight); }
console.log(objHeight);
console.log($obj.height());
console.log($obj.css("height"));
}
Chrome logs expected values:
577, 187,187, 187px
But Safari logs very unusual values:
682, 195, 0, 0px
When i see the generated html it is absolutely same for the two browsers:
<div id="itemImgsContainer" class="flexslider singleSmoothHeight">
<div class="flex-viewport" style="overflow: hidden; position: relative; height: 187px;">
<ul class="slides" style="width: 600%; transition-duration: 0s; transform: translate3d(0px, 0px, 0px);">
<li class="item flex-active-slide" style="width: 342px; float: left; display: block;"><img id="img_product_big_1085" itemprop="image" src="img_big.jpg" title="title" border="0" class="ui-corner-all"></li>
<li class="item" style="width: 342px; float: left; display: block;"><img src="img1.jpg" title="mytitle" border="0" class="ui-corner-all"></li>
<li class="item" style="width: 342px; float: left; display: block;"><img src="img2.jpg" title="title" border="0" class="ui-corner-all"></li>
</ul>
</div>
<ol class="flex-control-nav flex-control-paging">
<li><a class="flex-active">1</a></li><li><a>2</a></li><li><a>3</a></li>
</ol>
</div>
the difference is only in the height where Safari shows 195px instead.
This happens only on iPhone Safari, and not any other popular browser.
Any help will be appreciated.
EDIT
After some experiments i found out that this happens only if i click on a tag that uses "flippable" efect. If i put on this a tag e.stopPropagation(); this issue disappears. I know that there is no logic for this behavior, because the issue is on another page than this, but these are the facts.
EDIT 2
Here is some more code that shows how flexslider is called:
$('.flexslider.singleSmoothHeight li:first-child').imagesLoaded(function() {
$(this).parents('.singleSmoothHeight').flexslider({
animation: 'slide',
slideshow: false,
animationLoop: false,
directionNav: false,
smoothHeight: true
});
});
Here is a link with clip with the behavior in device simulator (iPhone 6+ in this case):
http://bksito.com/aftco_iPhone_tests.avi
Note that the Safari is in device emulator mode in firsts steps, and last tests are on Safari emulator mode. I'm so confused why only on devices this behavior occurs.
When you have these kind of issue, the unique solution is to call all the jQuery functions using chain:
$(...).css( ... ).height( ... ).animate( ... ). ...;
Other solution is to use a timer setted to 0, in order to get the painter refresh the DOM.
$(...).css( ... );
setTimeout(function(){
$(...).animate( ... );
},0);
The problem is that, when I close the popup without pausing the video, the audio keeps playing. I cannot pause the video while closing the popup. The complete code is give below.
//html code
<style>
.yourModalClass {
padding: 0 1.5em 1em;
border-radius: 5px;
max-width: 380px;
color:#fff;
}
.yourModalClass a {
color:#fff;
}
</style>
abc
<div id="yourModalId" class="yourModalClass" style="display:none; margin-left: -20%; margin-right: 20%">
<h2>abc</h2>
<video width="600" height="400" controls="">
<source src="abc.mp4" type="video/mp4"/>
Your browser does not support HTML5 video.
</video>
</div>
<script>
$('#yourModalId').modality({
effect: 'slide-up'
});
</script>
//javascript
/* #author: Himanshu Kandpal (cse10324.sbit#gmail.com)*/
;(function(e,t,n,r){var i="modality",s=e("body")[0],o= {autoBind:true,clickOffToClose:true,closeOnEscape:true,effect:"",innerClass:"mm-wrap",modalClass:"modality-modal",onClose:"",onOpen:"",openClass:"mm-show",openOnLoad:false,userClass:""},u=function(t,n){var r=this;r.defaults=o;r.id=e(t).attr("id");r.settings=e.extend({},o,n);r.$modal=e(t).wrap('<div class="'+r.settings.modalClass+" "+r.settings.effect+" "+r.settings.userClass+'">'+'<div class="'+r.settings.innerClass+'">'+"</div>"+"</div>").show();r.$wrapper=r.$modal.parents("."+r.settings.modalClass);r.$triggers=e('a[href="#'+r.id+'"], [data-modality="#'+r.id+'"]');if(r.settings.autoBind){r.$triggers.each(function(){r.setTrigger(e(this))})}if(r.settings.clickOffToClose){r.$wrapper.click(function(e){e.preventDefault();if(e.target==r.$wrapper[0])r.close()})}if(r.settings.closeOnEscape){e(s).keyup(function(e){if(e.keyCode==27)r.close()})}if(navigator.appVersion.indexOf("MSIE 7.")!=-1){r.$wrapper.prepend('<div class="mm-ghost"></div>')}if(r.settings.openOnLoad)r.open();return r};e.extend(u.prototype,{open:function(e){this.$wrapper.add(s).addClass(this.settings.openClass);if(typeof this.settings.onOpen=="function")this.settings.onOpen();if(typeof e=="function")e();return this},close:function(e){this.$wrapper.add(s).removeClass(this.settings.openClass);if(typeof this.settings.onClose=="function")this.settings.onClose();if(typeof e=="function")e();return this},toggle:function(e){return this.isOpen()?this.close(e):this.open(e)},isOpen:function(){return this.$wrapper.hasClass(this.settings.openClass)},setTrigger:function(e){var t=this;e.click(function(e){e.preventDefault();t.toggle()});return t}});e.extend(u,{instances:{},init:function(e,t){var n={},i=this,s=0;e.each(function(){var e=new i(this,t);i.instances[e.id]=n[s]=e});return n[1]===r?n[0]:n}});e[i]=u;e.fn[i]=function(t){return e[i].init(this,t)}})(jQuery,window,document);
add id to the video controler element
call after slide up
$('#videoID')[0].pause();
$("#videoID")[0] will return you the DOM element not the jQuery object as the pause method is not the jquery method its the DOM method
I have something very simple but I can not make it work correctly in Webkit and Mozilla
This is my HTML
<li style="padding-bottom: 10px;" class='product'>
<span class ='handle' style="cursor:move; float:left; margin-top:40px; margin-right:8px; margin-bottom:30px; display:none;">
<%= image_tag "page/arrow.png"%>
</span>
<table >
<tr style="border:5px; solid: #444">
<td class="product_contents" style="vertical-align: top;" >
<div class="product_contents" style="width: 480px; font-size: 100%; font-weight: bold; color: #333; margin-bottom: 10px; word-wrap: break-word; overflow: auto;">
STUFF HERE
</div>
<p class="product_contents" style="width: 480px; font-size: 93%; line-height: 150%; word-wrap: break-word; overflow: auto;">
MORE STUFF HERE
</p>
</td>
</tr>
</table>
</li>
And this is my JQuery:
jQuery(function($) {
$(".product").mouseenter(
function () {
$(this).find(".handle").css('display', 'inline'); //show();
$(this).css('background-color','#fffdef');
$(this).find(".product_contents").css('width', '450px');
});
$(".product").mouseleave(
function () {
$(this).find(".handle").css('display', 'none'); //.hide();
$(this).css('background-color','#ffffff');
$(this).find(".product_contents").css('width', '480px');
});
});
Nothing fancy here at all and it works as I expect in Firefox. The image in handle appears on the left and it displaces the content to the right, the content also change colors and size to match the image. PErfect.
But in Webkit it changes the color and the size but there is no displacement. What I want to achieve is pretty basic, there is a better approach?
I can use Jquery but I can not use any plugin.
I'm not sure if I understood your problem right, but I would recommend to try jQuery's show/hide functions:
$(this).find(".handle").show();
$(this).find(".handle").hide();
This one works for me in Firefox, and fails for Conkeror (which was surprising), and fails for SRWare Iron (which is a Chrome-based browser).
The problem seems to be related to the fact that the table is inside a <li> element. For some reason, Firefox treats this table as an inline element, and the other browsers as a block element. Since it is a block element, the table is pushed to the next line, and is not displaced, because the handle is on the previous line. Changing the display style of the table to inline-table fixed the issue for me.
You can hide an element by using the CSS display property and setting it to none.
$("element").style.display = "none"; // hide element
$("element").style.display = "block"; // show element (or inline)
So I have a div whose content is generated at runtime it initially has no height associated with it. When it's generated according to firebug and from what I can alert with js the div still has a height of 0. However, looking at the read-only properties with firebug I can see that it has an offset height of 34. It's this value that I need. Hopefully it's obvious but in case it isn't, this number is variable, it's not always 38.
So, I thought that I could just get that by doing this via jquery...
$("#parentDiv").attr('offsetHeight');
or this with straight js...
document.getElementById("parentDiv").offsetHeight;
But all that is returned is 0. Does it have anything to do with the fact that offset height is a read-only property in this instance? How can I get this height? I mean firebug is figuring it out somehow so it seems like I should be able to.
Edit:
Here's a sample of what the div looks like right now...
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML Strict//EN"><META http-equiv="Content-Type" content="text/html; charset=utf-8">
<HTML style="OVERFLOW: hidden; HEIGHT: 100%" xmlns="http://www.w3.org/1999/xhtml"><BODY><FORM id="aspnetForm" name="aspnetForm" action="blah.aspx" method="post"><DIV id="container">
<DIV id="ctl00_BodyContentPlaceHolder_Navigation" style="Z-INDEX: 1; LEFT: 1597px; POSITION: absolute; TOP: 67px">
<DIV class="TransparentBg" id="TransparentDiv" style="MARGIN-TOP: 10px; MARGIN-RIGHT: 10px; HEIGHT: 94px; TEXT-ALIGN: center">
</DIV>
<DIV class="Foreground" id="ForegroundId" style="MARGIN-TOP: 10px; MARGIN-RIGHT: 10px; TEXT-ALIGN: center">
<DIV id="ctl00_BodyContentPlaceHolder_Navigation1" style="WIDTH: 52px; COLOR: black; HEIGHT: 52px; BACKGROUND-COLOR: transparent; -moz-user-focus: normal">
<IMG style="FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod = scale src='../images/image.gif'); CURSOR: pointer" height="52" hspace="0" src="..." width="52" />
</DIV>
<DIV id="ctl00_BodyContentPlaceHolder_UserControl" name="ctl00_BodyContentPlaceHolder_UserControl">
<IMG style="DISPLAY: block; VERTICAL-ALIGN: bottom; CURSOR: pointer" height="17" src="..." width="16" />
<IMG style="VERTICAL-ALIGN: top; CURSOR: pointer" height="17" src="..." width="16" />
</DIV>
</DIV>
</DIV>
</DIV></FORM></BODY></HTML>
This code is being generated by a control in a separate library. So here's the actual code creating it in my .aspx page.
<blah:blahControl ID="control" runat="server" />
Ok, it's edited slightly but thats a whole lot more HTML than I had before. The div I was referring to as "parentDiv" before is called "ctl00_BodyContentPlaceHolder_UserControl" up there. That code includes the div in question, it's sibling, parent, grandparent and children. It's almost a direct copy from firebug.
Update:
I should have mentioned this is being done in IE 7. It seemed to work fine one time in Firefox, but it's returning 0 now. Does this provide any new insights of possible work-arounds or anything?
... You all must think I'm nuts.
Update:
Some styling...
.TransparentBg
{
background-color: white;
filter:alpha(opacity=50);
-moz-opacity:0.5;
-khtml-opacity: 0.5;
opacity: 0.5;
}
.Foreground
{
position: absolute;
top: 0px;
}
Are you sure the element is included in the document tree, and rendered? (ie. not “display: none”, but “visibility: hidden” is OK.)
An element that is not actually taking part in the document render process has no dimensions, and will give an offsetWidth/Height of 0.
ETA after code sample added: with your exact code, I get offsetHeight on the div of ‘17’. The first image is sized correctly, the second has no size.
This is correct as rendered(*). Any images that fail to load are replaced by their alt text as an inline span. Your image has no alt text, so it is replaced by an empty string. Normally, as an inline element, this cannot be set to any particular size. The exception is the first image, because you've given it ‘display: block’, which makes it amenable to the explicit sizing provided by width/height.
In Quirks Mode, you would have got little ‘broken image’ icons sized the same as the images were supposed to be. This does not happen in Standards Mode because it is assumed that you know how to use alt text properly if you're using standards.
Either way, the dimensions measurement works fine for me if I replace the "..." URLs with real working addresses.
(*: although you can't actually see it because of the rather weird ‘overflow-hidden’ on html and ‘left: 1597px;’ combo. Well, unless you have a really wide monitor!)
Are you sure it's not a Heisenbug? If you are setting the height somewhere programmatically and then trying to read it soon later, there is a chance DOM would not have updated.
Loading this file with a valid IMG SRC gives 3 alert boxes of "37". Without valid IMG SRC it gives "17" on all three.
What version of Jquery are you using? And which version of FireFox/IE?
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML Strict//EN"><META http-equiv="Content-Type" content="text/html; charset=utf-8">
<HTML style="OVERFLOW: hidden; HEIGHT: 100%" xmlns="http://www.w3.org/1999/xhtml">
<HEAD>
<script type="text/javascript" src="jquery.js"></script>
</HEAD>
<BODY>
<FORM id="aspnetForm" name="aspnetForm" action="blah.aspx" method="post">
<DIV id="container">
<DIV id="ctl00_BodyContentPlaceHolder_Navigation" style="Z-INDEX: 1; LEFT: 1597px; POSITION: absolute; TOP: 67px">
<DIV class="TransparentBg" id="TransparentDiv" style="MARGIN-TOP: 10px; MARGIN-RIGHT: 10px; HEIGHT: 94px; TEXT-ALIGN: center">
</DIV>
<DIV class="Foreground" id="ForegroundId" style="MARGIN-TOP: 10px; MARGIN-RIGHT: 10px; TEXT-ALIGN: center">
<DIV id="ctl00_BodyContentPlaceHolder_Navigation1" title="Click to pan the map." style="WIDTH: 52px; COLOR: black; HEIGHT: 52px; BACKGROUND-COLOR: transparent; -moz-user-focus: normal">
<IMG style="FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod = scale src='../images/image.gif'); CURSOR: pointer" height="52" hspace="0" src="..." width="52" />
</DIV>
<DIV id="ctl00_BodyContentPlaceHolder_UserControl" name="ctl00_BodyContentPlaceHolder_UserControl">
<IMG style="DISPLAY: block; VERTICAL-ALIGN: bottom; CURSOR: pointer" height="17" src="je_fanmap_unavailable.JPG" width="16" />
<IMG style="VERTICAL-ALIGN: top; CURSOR: pointer" height="17" src="je_fanmap_unavailable.JPG" width="16" />
</DIV>
</DIV>
</DIV>
<script type="text/javascript">
$(window).load(function () {
alert($("#ctl00_BodyContentPlaceHolder_UserControl").attr('offsetHeight'));
alert(document.getElementById("ctl00_BodyContentPlaceHolder_UserControl").offsetHeight);
alert($("#ctl00_BodyContentPlaceHolder_UserControl").height());
});
</script>
</DIV>
</FORM>
</BODY>
Try calling the offset function once all the DOM and images are fully loaded using load() instead of document.ready().
$(window).load(function () {
//Put the code for the height here
});
I just found an issue where I was getting the offsetHeight of an element when the doc was ready but it was in a container that was hidden.
It resulted in a offsetHeight value of 0 but firebug said it had a height of 32.