video.js: force initialization of already manually initialized video - javascript

I'm dynamically generating and changing the content of my site with javascript.
I'm adding video files and the videojs-javascript-files by javascript and initialize the video by calling _V_(videos[i].id);.
However, initializing the video only works at the first time!
When I then change the content of the site and then move to the video's page again, initializing the video again (the video-tag has still the same id) does not work.
The browser's HTML5 videoplayer is there but not the videojs-styled one.
Is there any other way I could "force" initialization of the player? What could cause this problem?
This is my script:
videoPlayer = {
check: function() {
videos = document.getElementsByTagName("video");
if (videos.length > 0) {
this.init();
}
},
init: function() {
if (isPlayer) {
//alert("init");
for (var i = 0; i < videos.length; i++) var player = _V_(videos[i].id, {}, function() {
alert("player init!")
});
}
else {
this.build();
}
},
build: function() {
//alert("build");
if (isPlayer == false) {
var head = document.getElementsByTagName("head")[0];
var videoScript = document.createElement('script');
videoScript.type = 'text/javascript';
videoScript.src = './min/g=videojs';
var videocss = document.createElement('link');
videocss.type = 'text/css';
videocss.rel = 'stylesheet';
videocss.href = './min/g=videocss';
isPlayer = true;
videoScript.onload = this.init;
head.appendChild(videocss);
head.appendChild(videoScript);
}
}
}
Thank you very much in advance!

Have you tried creating a new video element and (re)initializing it instead of re-using the previous video element?
You can also try to "reset" everything, src, tracks, captions, etc with the new values

I know it's pretty late, but you could try checking the children of the video element. For example, if it already contains a div of class vjs-poster do nothing, else initialize video-js.

Related

why does this keep playing same video instead of random new video?

I'm making a random order video player, adapting code from here but the same video just keeps playing, even though I can see (from text above the video) that the random ordering is working. Live version is here.
Is the problem with the appendChild meaning the new video is end of a list but the first in list keeps playing? I tried replaceChild but that didn't work.
<script type="text/javascript">
$(document).ready(function(){
var videos = [
[{type:'mp4', 'src':'carlos/one-carlostest.mp4'}],
[{type:'mp4', 'src':'carlos/two-carlostest.mp4'}],
[{type:'mp4', 'src':'carlos/three-carlostest.mp4'}],
[{type:'mp4', 'src':'carlos/four-carlostest.mp4'}],
[{type:'mp4', 'src':'carlos/five-carlostest.mp4'}]
];
// selecting random item from array as first to be played
var randomitem = videos[Math.floor(Math.random()*videos.length)];
// This function adds a new video source (dynamic) in the video html tag
function videoadd(element, src, type) {
var source = document.createElement('source');
source.src = src;
source.type = type;
element.appendChild(source);
}
// this function fires the video for particular video tag
function newvideo(src){
var vid = document.getElementById("myVideo");
videoadd(vid,src ,'video/ogg');
vid.autoplay = true;
vid.load();
vid.play();
}
// function call
newvideo(randomitem[0].src)
// Added an event listener so that everytime the video finishes ,a new video is loaded from array
document.getElementById('myVideo').addEventListener('ended',handler,false);
function handler(){
var newRandom = videos[Math.floor(Math.random()*videos.length)];
newvideo(newRandom[0].src)
document.getElementById("monitor").innerHTML = "randomitem is " + newRandom[0].src;
}
})
</script>
Also, if anyone can tell me why the autoplay never works that'd be appreciated, though it's the least of my problems.
I have kinda found this solution for your video playing one after other. now in your JS file, now you just will need to add your video src path.
var vidElement = document.getElementById('video');
var vidSources = [
"https://lutins.co.uk/carlos/one-carlostest.mp4",
"http://www.w3schools.com/html/movie.mp4"
];
var activeVideo = Math.floor((Math.random() * vidSources.length));
vidElement.src = vidSources[activeVideo];
vidElement.addEventListener('ended', function(e) {
// update the active video index
activeVideo = (++activeVideo) % vidSources.length;
if(activeVideo === vidSources.length){
activeVideo = 0;
}
// update the video source and play
vidElement.src = vidSources[activeVideo];
vidElement.play();
});
video {
width:350px;
}
<p>wowww you got it!</p>
<video src="https://lutins.co.uk/carlos/one-carlostest.mp4" id="video" autoplay muted playsinline></video>
Change the randomIt variable into a callback, only this way, it will generate new random number each time it get call.
// I have change randomitem into a function with ofcourse a proper name
var getRandomItem = function() {
return videos[Math.floor(Math.random()*videos.length)];
}
You should also call it properly like this:
//newvideo(randomitem[0].src) -> change it to
newvideo(getrandomItem().src)
There might also other adjustments requires for your code to work.

JS - play different sound after each click

I have a single link and I want the link to play different sounds each time it is clicked. When I click the link it plays both sounds at the same time but I want one sound at a time
var bleep = new Audio('hello.mp3') ;
bleep.src = "hello.mp3" ;
var bleep2 = new Audio('goodbye.mp3') ;
bleep2.src = "goodbye.mp3";
Home
You should make a function out of it that checks which sound was clicked last time. Also, you neither need to set the .src property or pass a string to the play method.
JS:
var bleep = new Audio('hello.mp3');
var bleep2 = new Audio('goodbye.mp3');
var playFirst = true;
function playSound() {
if (playFirst) {
bleep.play();
} else {
bleep2.play();
}
playFirst = !playFirst;
}
HTML:
Home
Instead of attaching the event listener inline as onclick, attach it with JS using addEventListener. This allows you to pick which audio clip to play:
var helloSound = new Audio('hello.mp3');
helloSound.src = "hello.mp3";
var goodbyeSound = new Audio('goodbye.mp3');
goodbyeSound.src = "goodbye.mp3";
var homeLink = document.getElementById('home-link');
homeLink.addEventListener('click', function () {
if (/* condition to play hello */) {
helloSound.play();
} else {
goodbyeSound.play();
}
});
Markup:
Home

Why does this "loading message" script not work in FF?(javascript)

I have this script which should show the text "Loading..." while images are loading, then change the text to "loaded" when all images are loaded. I added a button to load new images to make sure that it works for dynamically loaded images as well.
This works perfectly in Chrome but in Firefox the "Loading..." text never appears. I have no idea why this would be. The page begins loading and not all images are loaded so it should create the text "Loading.." but it doesn't. Then when all images are done loading the text "Loading" appears.
I just don't get why one message would appear and the other wouldn't. Especially because there are no qualifications that have to be met before creating the "Loading..." text, it should just fire automatically.
jsfiddle Example | Full Page Example
$(document).ready(function() {
var checkComplete = function() {
if($('img').filter(function() {return $('img').prop('complete');}).length == $('img').length) {
$('.status').text('Loaded');
} else {
$('.status').text('Loading...');
}
};
$('img').on('load',function() {
checkComplete();
});
$('#button').click(function() {
$('img.a').attr('src' , 'http://farm9.staticflickr.com/8545/8675107979_ee12611e6e_o.jpg');
$('img.b').attr( 'src' , 'http://farm9.staticflickr.com/8382/8677371836_651f586c99_o.jpg');
checkComplete();
});
checkComplete();
});
You have several issues in the code.
First off, the checkComplete() function is not written correctly. It should be this:
var checkComplete = function() {
var imgs = $('img');
if(imgs.filter(function() {return this.complete;}).length == imgs.length) {
$('.status').text('Loaded');
} else {
$('.status').text('Loading...');
}
};
The main fix here is that the filter callback needs to refer to this.complete, not to $('img').prop('complete') because you are trying to filter a single item at a time.
Second off, you are relying on both .complete and .load working correctly AFTER you've changed the .src value. This is explicitly one of the cases where they do not work properly in all browsers.
The bulletproof way to work around this is to create a new image object for the new images, set the onload handler before you set the .src value and when both onload handlers have fired, you will know that both new images are loaded and you can replace the once you have in the DOM with the new ones.
Here is a version that works in FF:
$(document).ready(function() {
$('#button').click(function() {
var imgA = new Image();
var imgB = new Image();
imgA.className = "a";
imgB.className = "b";
var loaded = 0;
imgA.onload = imgB.onload = function() {
++loaded;
if (loaded == 2) {
$("img.a").replaceWith(imgA);
$("img.b").replaceWith(imgB);
$('.status').text('Loaded');
}
}
// the part with adding now to the end of the URL here is just for testing purposes to break the cache
// remove that part for deployment
var now = new Date().getTime();
imgA.src = 'http://farm9.staticflickr.com/8545/8675107979_ee12611e6e_o.jpg?' + now;
imgB.src = 'http://farm9.staticflickr.com/8382/8677371836_651f586c99_o.jpg?' + now;
$('.status').text('Loading...');
});
});
Working demo: http://jsfiddle.net/jfriend00/yy7GX/
If you want to preserve the original objects, you can use the newly created objects only for preloading the new images and then change .src after they've been preloaded like this:
$(document).ready(function() {
$('#button').click(function() {
var imgA = new Image();
var imgB = new Image();
var loaded = 0;
imgA.onload = imgB.onload = function() {
++loaded;
if (loaded == 2) {
$("img.a")[0].src = imgA.src;
$("img.b")[0].src = imgB.src;
$('.status').text('Loaded');
}
}
// the part with adding now to the end of the URL here is just for testing purposes to break the cache
// remove that part for deployment
var now = new Date().getTime();
imgA.src = 'http://farm9.staticflickr.com/8545/8675107979_ee12611e6e_o.jpg?' + now;
imgB.src = 'http://farm9.staticflickr.com/8382/8677371836_651f586c99_o.jpg?' + now;
$('.status').text('Loading...');
});
});
Working demo of this version: http://jsfiddle.net/jfriend00/ChSQ5/
From the jQuery API .load method
Caveats of the load event when used with images
A common challenge developers attempt to solve using the `.load()` shortcut is to execute a function when an image (or collection of images) have completely loaded. There are several known caveats with this that should be noted. These are:
It doesn't work consistently nor reliably cross-browser
It doesn't fire correctly in WebKit if the image src is set to the same src as before
It doesn't correctly bubble up the DOM tree
Can cease to fire for images that already live in the browser's cache

javascript preloader/progress/percentage

I'm having trouble finding any good information on how to make a javascript(or jquery) progress bar WITH text that tells you the percentage.
I don't want a plug in, I just want to know how it works so that I can adapt it to what I need. How do you preload images and get a variable for the number of images that are preloaded. Also, how do you change html/css and-or call a function, based on the number of images that are loaded already?
<img> elements have an onload event that fires once the image has fully loaded. Therefore, in js you can keep track of the number of images that have loaded vs the number remaining using this event.
Images also have corresponding onerror and onabort events that fire when the image fails to load or the download have been aborted (by the user pressing the 'x' button). You also need to keep track of them along with the onload event to keep track of image loading properly.
Additional answer:
A simple example in pure js:
var img_to_load = [ '/img/1.jpg', '/img/2.jpg' ];
var loaded_images = 0;
for (var i=0; i<img_to_load.length; i++) {
var img = document.createElement('img');
img.src = img_to_load[i];
img.style.display = 'hidden'; // don't display preloaded images
img.onload = function () {
loaded_images ++;
if (loaded_images == img_to_load.length) {
alert('done loading images');
}
else {
alert((100*loaded_images/img_to_load.length) + '% loaded');
}
}
document.body.appendChild(img);
}
The example above doesn't handle onerror or onabort for clarity but real world code should take care of them as well.
What about using something below:
$('#btnUpload').click(function() {
var bar = document.getElementById('progBar'),
fallback = document.getElementById('downloadProgress'),
loaded = 0;
var load = function() {
loaded += 1;
bar.value = loaded;
/* The below will be visible if the progress tag is not supported */
$(fallback).empty().append("HTML5 progress tag not supported: ");
$('#progUpdate').empty().append(loaded + "% loaded");
if (loaded == 100) {
clearInterval(beginLoad);
$('#progUpdate').empty().append("Upload Complete");
console.log('Load was performed.');
}
};
var beginLoad = setInterval(function() {
load();
}, 50);
});
JSFIDDLE
You might also want to try HTML5 progress element:
<section>
<p>Progress: <progress id="p" max=100><span>0</span>%</progress></p>
<script>
var progressBar = document.getElementById('p');
function updateProgress(newValue) {
progressBar.value = newValue;
progressBar.getElementsByTagName('span')[0].textContent = newValue;
} </script>
</section>
http://www.html5tutorial.info/html5-progress.php

Dashcode webapp flickers upon transition, only in iPhone Safari

I created a simple RSS web app using the template in Dashcode. Problem is, when choosing items in the list from the feed the transition flickers (even with the default settings). I am guessing its because of the images in the posts.
I tried disabling the transitions completely but even then I get a flickering when returning to the list. This problem does not appear to affect safari on OSX only on the iphone.
Here is the code that I think is responsible:
var topStories = parseInt(attributes.topStories, 30);
function load()
{
dashcode.setupParts();
// set today's date
var todaysDate = document.getElementById("todaysDate");
todaysDate.innerText = createDateStr(new Date()).toUpperCase();
setupFilters("headlineList");
// This message checks for common errors with the RSS feed or setup.
// The handler will hide the split view and display the error message.
handleCommonErrors(attributes.dataSource,
function(errorMessage) {
var stackLayout = document.getElementById("StackLayout")
if (stackLayout) {
stackLayout.style.display = 'none';
}
showError(errorMessage);
});
// get notifications from the stack layout when the transition ends
document.getElementById("StackLayout").object.endTransitionCallback = function(stackLayout, oldView, newView) {
// clear selection of lists when navigating to the first view
var firstView = stackLayout.getAllViews()[0];
if (newView == firstView) {
document.getElementById("headlineList").object.clearSelection(true);
}
}
}
function articleClicked(event)
{
document.getElementById("StackLayout").object.setCurrentView("articlePage", false, true);
}
function backToArticlesClicked(event)
{
document.getElementById("StackLayout").object.setCurrentView("frontPage", true);
}
function readMoreClicked(event)
{
var headlineList = dashcode.getDataSource('headlineList');
var secondHeadlines = dashcode.getDataSource("secondHeadlines");
var selectedItem = null;
if (headlineList.hasSelection()) {
selectedItem = headlineList.selectedObjects()[0];
} else if (secondHeadlines.hasSelection()) {
selectedItem = secondHeadlines.selectedObjects()[0];
}
if (selectedItem) {
var link = selectedItem.valueForKeyPath('link');
// If the link is an object, not a string, then this may be an ATOM feed, grab the actual
// href from the href attr
if (typeof(link) == 'object') {
link = selectedItem.valueForKeyPath('link.$href');
// If the link is an array (there is more then one link), just grab the first one
if (DC.typeOf(link) == 'array') {
link = link[0];
}
}
window.location = link;
}
}
var headlineListDataSource = {
// The List calls this method once for every row.
prepareRow: function(rowElement, rowIndex, templateElements) {
if (rowIndex >= topStories) {
templateElements['headlineDescription'].style.display = 'none';
templateElements['headlineTitle'].style.fontSize = '15px';
}
}
};
The following CSS rule fixed all of my "-webkit-transition" animation flickering issues on the iPad:
body {-webkit-transform:translate3d(0,0,0);}
I am not sure how well that applies to your problem but in general you should set the backface visibility to hidden if not needed. That will most likely kill all flickering on a page.
-webkit-backface-visibility: hidden;

Categories