forked from 0x2620/oxjs
video updates (playlists)
This commit is contained in:
parent
a7c94a8019
commit
0369eaff14
2 changed files with 334 additions and 110 deletions
|
|
@ -11,77 +11,42 @@ Ox.VideoElement = function(options, self) {
|
|||
})
|
||||
.options(options || {});
|
||||
|
||||
self.options.src = Ox.isArray(self.options.src) ? self.options.src : [self.options.src];
|
||||
|
||||
Ox.print('VIDEO ELEMENT OPTIONS', self.options)
|
||||
|
||||
self.currentPart = 0;
|
||||
self.duration = 0;
|
||||
self.durations = self.options.src.map(function() {
|
||||
return 0;
|
||||
});
|
||||
self.offsets = [];
|
||||
self.parts = self.options.src.length;
|
||||
self.items = [];
|
||||
self.paused = true;
|
||||
self.$video = $('<div>');
|
||||
|
||||
self.$videos = self.options.src.map(function(src, i) {
|
||||
return $('<video>')
|
||||
.css({position: 'absolute'})
|
||||
.bind({
|
||||
ended: function(e) {
|
||||
alert(e);
|
||||
if (i < self.parts - 1) {
|
||||
setCurrentPart(self.currentPart + 1);
|
||||
self.video.play();
|
||||
} else {
|
||||
self.ended = true;
|
||||
self.paused = true;
|
||||
that.triggerEvent('ended');
|
||||
}
|
||||
},
|
||||
loadedmetadata: function() {
|
||||
self.durations[i] = self.videos[i].duration;
|
||||
Ox.print(i, 'lm', self.durations);
|
||||
if (Ox.every(self.durations)) {
|
||||
self.duration = Ox.sum(self.durations);
|
||||
self.offsets = Ox.range(self.parts).map(function(i) {
|
||||
return Ox.sum(Ox.sub(self.durations, 0, i));
|
||||
});
|
||||
Ox.print('s.o', self.offsets)
|
||||
that.triggerEvent('loadedmetadata');
|
||||
}
|
||||
},
|
||||
progress: function() {
|
||||
|
||||
},
|
||||
seeked: function() {
|
||||
that.triggerEvent('seeked');
|
||||
},
|
||||
seeking: function() {
|
||||
that.triggerEvent('seeking');
|
||||
},
|
||||
stop: function() {
|
||||
self.video.pause();
|
||||
that.triggerEvent('ended');
|
||||
if (Ox.isFunction(self.options.src)) {
|
||||
self.isPlaylist = true;
|
||||
self.currentItem = 0;
|
||||
self.currentPage = 0;
|
||||
self.loadedMetadata = false;
|
||||
self.pageLength = 2;
|
||||
self.options.src(function(items) {
|
||||
self.numberOfItems = items;
|
||||
self.numberOfPages = Math.ceil(self.numberOfItems / self.pageLength);
|
||||
loadPages(function() {
|
||||
Ox.print('VIDEO PAGES LOADED');
|
||||
setCurrentItem(0);
|
||||
if (!self.loadedMedatata) {
|
||||
self.loadedMetadata = true;
|
||||
that.triggerEvent('loadedmetadata');
|
||||
that.triggerEvent('pointschange'); // fixme: needs to be triggered again, loadedmetadata messes with duration
|
||||
}
|
||||
})
|
||||
.attr(Ox.extend({
|
||||
preload: 'metadata',
|
||||
src: src
|
||||
}, i == 0 && self.options.autoplay ? {
|
||||
autoplay: 'autoplay'
|
||||
} : {}))
|
||||
.hide()
|
||||
.appendTo(that.$element);
|
||||
});
|
||||
self.videos = self.$videos.map(function($video) {
|
||||
return $video[0];
|
||||
});
|
||||
self.$video = self.$videos[0].show();
|
||||
self.video = self.$video[0];
|
||||
});
|
||||
});
|
||||
} else {
|
||||
self.numberOfItems = 1;
|
||||
self.items.push(loadItem(self.options.src));
|
||||
}
|
||||
|
||||
function getCurrentPage() {
|
||||
return Math.floor(self.currentItem / self.pageLength);
|
||||
}
|
||||
|
||||
function getCurrentTime() {
|
||||
return self.offsets[self.currentPart] + self.video.currentTime;
|
||||
return self.items[self.currentItem].offsets[self.currentPart] + self.video.currentTime;
|
||||
}
|
||||
|
||||
function getset(key, value) {
|
||||
|
|
@ -95,15 +60,172 @@ Ox.VideoElement = function(options, self) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
function loadPage(page, callback) {
|
||||
Ox.print('VIDEO loadPage', page)
|
||||
//page = Ox.mod(page, self.numberOfPages);
|
||||
var loadedmetadata = 0,
|
||||
start = page * self.pageLength,
|
||||
stop = Math.min(start + self.pageLength, self.numberOfItems),
|
||||
pageLength = stop - start;
|
||||
if (!self.items[start]) {
|
||||
self.options.src([start, stop], function(data) {
|
||||
data.forEach(function(data, i) {
|
||||
self.items[start + i] = loadItem(data.parts, data.points, function(item) {
|
||||
if (++loadedmetadata == pageLength) {
|
||||
Ox.print('VIDEO page', page, 'loaded')
|
||||
callback && callback();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
Ox.print('PAGE IN CACHE')
|
||||
callback && callback();
|
||||
}
|
||||
}
|
||||
|
||||
function loadPages(callback) {
|
||||
var currentPage = self.currentPage,
|
||||
nextPage = Ox.mod(currentPage + 1, self.numberOfPages),
|
||||
previousPage = Ox.mod(currentPage - 1, self.numberOfPages)
|
||||
loadPage(currentPage, function() {
|
||||
if (nextPage != currentPage) {
|
||||
loadPage(nextPage, function() {
|
||||
if (previousPage != currentPage && previousPage != nextPage) {
|
||||
unloadPage(previousPage);
|
||||
}
|
||||
});
|
||||
}
|
||||
callback && callback();
|
||||
});
|
||||
}
|
||||
|
||||
function loadItem(src, points, callback) {
|
||||
src = Ox.isArray(src) ? src : [src];
|
||||
var item = {
|
||||
currentPart: 0,
|
||||
duration: 0,
|
||||
durations: src.map(function() {
|
||||
return 0;
|
||||
}),
|
||||
offsets: [],
|
||||
parts: src.length
|
||||
};
|
||||
if (points) {
|
||||
item.points = points;
|
||||
}
|
||||
item.$videos = src.map(function(src, i) {
|
||||
// in all browsers except firefox,
|
||||
// loadedmetadata fires only once per src
|
||||
src += '?' + Ox.uid();
|
||||
return $('<video>')
|
||||
.css({position: 'absolute'})
|
||||
.bind({
|
||||
ended: function() {
|
||||
if (i < self.parts - 1) {
|
||||
setCurrentPart(self.currentPart + 1);
|
||||
self.video.play();
|
||||
} /*else if (self.isPlaylist) {
|
||||
setCurrentItem(self.currentItem + 1);
|
||||
self.video.play();
|
||||
}*/ else {
|
||||
self.ended = true;
|
||||
self.paused = true;
|
||||
that.triggerEvent('ended');
|
||||
}
|
||||
},
|
||||
loadedmetadata: function() {
|
||||
item.durations[i] = item.videos[i].duration;
|
||||
if (self.isPlaylist && i == 0) {
|
||||
item.videos[0].currentTime = item.points[0];
|
||||
}
|
||||
if (Ox.every(item.durations)) {
|
||||
item.duration = Ox.sum(item.durations);
|
||||
item.offsets = Ox.range(item.parts).map(function(i) {
|
||||
return Ox.sum(Ox.sub(item.durations, 0, i));
|
||||
});
|
||||
//Ox.print('METADATA OF', src, 'LOADED', item)
|
||||
if (self.isPlaylist) {
|
||||
callback && callback();
|
||||
} else {
|
||||
setCurrentItem(0);
|
||||
that.triggerEvent('loadedmetadata');
|
||||
}
|
||||
}
|
||||
},
|
||||
progress: function() {
|
||||
// not implemented
|
||||
},
|
||||
seeked: function() {
|
||||
that.triggerEvent('seeked');
|
||||
},
|
||||
seeking: function() {
|
||||
that.triggerEvent('seeking');
|
||||
},
|
||||
stop: function() {
|
||||
// custom event to be triggered on removal from the DOM
|
||||
self.video.pause();
|
||||
self.video.src = '';
|
||||
that.triggerEvent('ended');
|
||||
}
|
||||
})
|
||||
.attr(Ox.extend({
|
||||
preload: 'metadata',
|
||||
src: src
|
||||
}, i == 0 && self.options.autoplay ? {
|
||||
autoplay: 'autoplay'
|
||||
} : {}))
|
||||
.hide()
|
||||
.appendTo(that.$element);
|
||||
});
|
||||
item.videos = item.$videos.map(function($video) {
|
||||
return $video[0];
|
||||
});
|
||||
return item;
|
||||
}
|
||||
|
||||
function setCurrentItem(item) {
|
||||
Ox.print('scI', item);
|
||||
var interval;
|
||||
item = Ox.mod(item, self.numberOfItems);
|
||||
self.video && self.video.pause();
|
||||
if (self.items[item]) {
|
||||
set();
|
||||
} else {
|
||||
that.triggerEvent('seeking');
|
||||
interval = setInterval(function() {
|
||||
Ox.print('ITEM', item, 'NOT AVAILABLE');
|
||||
if (self.items[item]) {
|
||||
clearInterval(interval);
|
||||
that.triggerEvent('seeked');
|
||||
set();
|
||||
}
|
||||
}, 250);
|
||||
}
|
||||
function set() {
|
||||
self.currentItem = item;
|
||||
self.currentPart = -1;
|
||||
setCurrentTime(0);
|
||||
if (self.isPlaylist) {
|
||||
that.triggerEvent('pointschange');
|
||||
that.triggerEvent('sizechange');
|
||||
self.currentPage = getCurrentPage();
|
||||
loadPages();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setCurrentPart(part) {
|
||||
Ox.print('sCP', part);
|
||||
var css = {};
|
||||
['left', 'top', 'width', 'height'].forEach(function(key) {
|
||||
css[key] = self.$video.css(key);
|
||||
});
|
||||
self.$video.hide();
|
||||
self.video.pause();
|
||||
self.$video = self.$videos[part].css(css).show();
|
||||
if (self.video) {
|
||||
self.video.pause();
|
||||
self.$video.hide();
|
||||
}
|
||||
self.$video = self.items[self.currentItem].$videos[part].css(css).show();
|
||||
self.video = self.$video[0];
|
||||
!self.paused && self.video.play();
|
||||
self.currentPart = part;
|
||||
|
|
@ -112,11 +234,12 @@ Ox.VideoElement = function(options, self) {
|
|||
|
||||
function setCurrentTime(time) {
|
||||
Ox.print('sCT', time);
|
||||
var currentPart, currentTime;
|
||||
Ox.loop(self.parts - 1, -1, -1, function(i) {
|
||||
if (self.offsets[i] <= time) {
|
||||
var currentPart, currentTime,
|
||||
item = self.items[self.currentItem];
|
||||
Ox.loop(item.parts - 1, -1, -1, function(i) {
|
||||
if (item.offsets[i] <= time) {
|
||||
currentPart = i;
|
||||
currentTime = time - self.offsets[i];
|
||||
currentTime = time - item.offsets[i];
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
|
@ -127,6 +250,22 @@ Ox.VideoElement = function(options, self) {
|
|||
self.video.currentTime = currentTime;
|
||||
}
|
||||
|
||||
function unloadPage(page) {
|
||||
//page = Ox.mod(page, self.numberOfPages);
|
||||
Ox.print('unloadPage', page)
|
||||
var start = page * self.pageLength,
|
||||
stop = Math.min(start + self.pageLength, self.numberOfItems);
|
||||
Ox.range(start, stop).forEach(function(i) {
|
||||
if (self.items[i]) {
|
||||
self.items[i].$videos.forEach(function($video) {
|
||||
$video[0].src = ''
|
||||
$video.remove();
|
||||
});
|
||||
delete self.items[i];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
that.animate = function() {
|
||||
self.$video.animate.apply(self.$video, arguments);
|
||||
return that;
|
||||
|
|
@ -149,18 +288,34 @@ Ox.VideoElement = function(options, self) {
|
|||
};
|
||||
|
||||
that.css = function() {
|
||||
self.$video.css.apply(self.$video, arguments);
|
||||
var interval;
|
||||
if (self.$video) {
|
||||
self.$video.css.apply(self.$video, arguments);
|
||||
} else {
|
||||
interval = setInterval(function() {
|
||||
Ox.print('VIDEO NOT YET AVAILABLE');
|
||||
if (self.$video) {
|
||||
clearInterval(interval);
|
||||
self.$video.css.apply(self.$video, arguments);
|
||||
}
|
||||
}, 250);
|
||||
}
|
||||
return that;
|
||||
};
|
||||
|
||||
that.duration = function() {
|
||||
return self.duration;
|
||||
// 86399
|
||||
return self.items[self.currentItem].duration;
|
||||
};
|
||||
|
||||
that.muted = function() {
|
||||
return getset('muted', arguments[0]);
|
||||
};
|
||||
|
||||
that.points = function() {
|
||||
return self.items[self.currentItem].points;
|
||||
};
|
||||
|
||||
that.pause = function() {
|
||||
self.paused = true;
|
||||
self.video.pause();
|
||||
|
|
@ -177,6 +332,16 @@ Ox.VideoElement = function(options, self) {
|
|||
return that;
|
||||
};
|
||||
|
||||
that.playNext = function() {
|
||||
Ox.print('PLAY NEXT')
|
||||
setCurrentItem(self.currentItem + 1);
|
||||
self.video.play();
|
||||
};
|
||||
|
||||
that.playPrevious = function() {
|
||||
setCurrentItem(self.currentItem - 1);
|
||||
};
|
||||
|
||||
that.src = function() {
|
||||
var ret;
|
||||
if (arguments.length == 0) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue