summaryrefslogtreecommitdiff
path: root/chimere/static/jme/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'chimere/static/jme/plugins')
-rw-r--r--chimere/static/jme/plugins/fullwindow.js549
-rw-r--r--chimere/static/jme/plugins/playlist.js301
-rw-r--r--chimere/static/jme/plugins/poster.js145
-rw-r--r--chimere/static/jme/plugins/timerange.js165
-rw-r--r--chimere/static/jme/plugins/track.js403
-rw-r--r--chimere/static/jme/plugins/ui.sounds.js69
6 files changed, 1632 insertions, 0 deletions
diff --git a/chimere/static/jme/plugins/fullwindow.js b/chimere/static/jme/plugins/fullwindow.js
new file mode 100644
index 0000000..46ae983
--- /dev/null
+++ b/chimere/static/jme/plugins/fullwindow.js
@@ -0,0 +1,549 @@
+/**
+ * fullwindow plugin for the jMediaelement project | http://github.com/aFarkas/jMediaelement
+ * @author Alexander Farkas
+ * Copyright 2010, Alexander Farkas
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ *
+ * API:
+ * $('video').enterFullWindow() - enters fullWindow
+ * $('video').exitFullWindow() - exits fullWindow
+ * $('video').supportsFullWindow() - is fullwindow / position fixed supported (feature detection, not browser sniffing!)
+ *
+ * Controls:
+ * an element with the class 'fullscreen' generates a fullwindow-togglebutton
+ *
+ * <a class="fullscreen" role="button" tabindex="0">toggle fullscreen</a>
+ *
+ * Documentation:
+ * http://protofunc.com/jme/plugins/fullwindow.html
+ */
+
+(function($){
+ $.support.cssPointerEvents = ('pointerEvents' in $('<div />')[0].style);
+ $.support.getBoundingClientRect = ('getBoundingClientRect' in $('<div />')[0]);
+
+ /* helper methods */
+ var pos = {
+ relative: 1,
+ absolute: 1
+ },
+ getPosedAncestors = function(elem){
+ var ret = [],
+ bodyReg = /^body|html$/i
+ ;
+ if(elem.jquery){
+ elem = elem[0];
+ }
+ elem = elem.parentNode;
+ while( elem && !bodyReg.test(elem.nodeName) ){
+ if( pos[ $.curCSS(elem, 'position') ] ){
+ ret.push(elem);
+ }
+ elem = elem.parentNode;
+ }
+
+ return $(ret);
+ };
+
+ var zIndexReg = /zIndex/;
+ $.fn.storeInlineStyle = function(styles, name){
+ if(!styles && !name){
+ name = 'storedInlineStyle';
+ } else if(typeof styles === 'string'){
+ name = styles;
+ styles = false;
+ } else {
+ name = name || 'storedInlineStyle';
+ }
+
+ return this.each(function(){
+ var data = $.data(this, name) || $.data(this, name, {}),
+ elemS = this.style,
+ elem = this
+ ;
+
+ if(!styles){
+ if(!data){return;}
+ $(this).css(data);
+ $.data(this, name, {});
+ } else {
+ $.each(styles, function(prop, val){
+ data[prop] = elemS[prop];
+ //ie7 reports zIndex always as inline-style
+ if( prop === 'zIndex' && data[prop] !== '' && !$.support.style && !zIndexReg.test( elem.style.cssText ) ){
+ data[prop] = '';
+ }
+ });
+ $(this).css(styles);
+ }
+ });
+ };
+
+ var videoBaseCSS = {
+ position: 'fixed',
+ zIndex: 99999,
+ width: 'auto',
+ height: 'auto'
+ },
+ parentsCss = {
+ position: 'static'
+ },
+ bodyCSS = {
+ overflow: 'hidden'
+ },
+ win = $(window),
+ doc = $(document),
+ doSize = function(winDim, max, model){
+ var ret = {};
+ ret[model[0]] = max[model[0]];
+ ret[model[1]] = max[model[0]] * model[2];
+
+ ret.bottom = (winDim.height / 2) - (ret.height / 2);
+ ret.top = ret.bottom;
+ ret.left = (winDim.width / 2) - (ret.width / 2);
+ ret.right = ret.left;
+ return ret;
+ },
+ getSize = function(rel, maxWidth, maxHeight){
+ var width = win.width(),
+ height = win.height()
+ ;
+
+ var winDim = {
+ width: win.width(),
+ height: win.height()
+ },
+ max = {
+ width: maxWidth ? Math.min(winDim.width, maxWidth) : winDim.width,
+ height: maxHeight ? Math.min(winDim.height, maxHeight) : winDim.height
+ }
+ ;
+
+ return doSize(winDim, max, (max.width / max.height > rel) ? ['height', 'width', rel] : ['width', 'height', 1 / rel] );
+ },
+ supportsFullWindow
+ ;
+
+ $.each(['Top', 'Left', 'Right', 'Bottom'], function(i, name){
+ videoBaseCSS['padding'+ name] = 0;
+ videoBaseCSS['margin'+ name] = 0;
+ videoBaseCSS['border'+ name +'Width'] = 0;
+ });
+
+ var windowOverlay = (function(){
+ var trans = /transparent|rgba\(0, 0, 0, 0\)/,
+ overlay = $('<div class="fullwindow-overlay" />')
+ .css({
+ position: 'fixed',
+ display: 'none',
+ right: 0,
+ bottom: 0,
+ top: 0,
+ left: 0,
+ zIndex: 99990
+ }),
+ isVisible, timer
+ ;
+
+ // IE7/IE8 retrigger
+ win.bind('resize', function(){
+ if(isVisible){
+ clearTimeout(timer);
+ timer = setTimeout(function(){
+ overlay.css({top: -1, left: -1, right: -1, bottom: -1});
+ setTimeout(function(){
+ overlay.css({top: 0, left: 0, right: 0, bottom: 0});
+ }, 1);
+ }, 100);
+ }
+ });
+
+ var pub = {
+ show: function(video){
+ if(!overlay || isVisible){return;}
+ var bgCol = overlay.css('backgroundColor'),
+ bgImg = overlay.css('backgroundImage')
+ ;
+ if( (!bgCol || trans.test( bgCol ) ) && ( !bgImg || bgImg == 'none' ) ){
+ overlay.css('backgroundColor', '#000');
+ }
+ overlay.insertAfter(video).show();
+ isVisible = true;
+ },
+ hide: function(){
+ if(!overlay || !isVisible){return;}
+ overlay.hide().css('backgroundColor', '').detach();
+ isVisible = false;
+ }
+ };
+
+ return pub;
+ })();
+
+ $(function(){
+ var div = $('<div style="visibility: hidden; postion: absolute; top: 0; left: 10px; padding: 10px;"><div style="position: fixed; top: 0;left: 0;" /></div>').appendTo('body');
+ supportsFullWindow = !($('div', div).offset().left);
+ div.remove();
+ });
+
+
+ var defaultOverlayCSS = {
+ position: 'fixed',
+ zIndex: 999996
+ };
+
+ $.fn.videoOverlay = function(o){
+ o = $.extend(true, {}, $.fn.videoOverlay.defaults, o);
+ if( !o.video ){return this;}
+ o.video = $(o.video);
+ var overlayCSS = $.extend({}, defaultOverlayCSS, o.startCSS),
+ dynPos = o.position
+ ;
+ if( !$.isFunction( o.position ) ){
+ $.each(o.position, function(styleName, posval){
+ overlayCSS[styleName] = posval;
+ });
+ o.position = function(css){
+ var ret = {};
+ for(var name in dynPos){
+ ret[name] = css[name];
+ }
+ return ret;
+ };
+ }
+
+ return this.each(function(){
+ var overlay = $(this);
+ o.video
+ .bind({
+ fullwindow: function(e, evt){
+ if( !evt.isFullwindow ){
+ //restore old css
+ overlay
+ .storeInlineStyle('fsstoredOverlay')
+ .removeClass(o.fullscreenClass)
+ ;
+ } else {
+ //store pre css
+ overlay
+ .storeInlineStyle(overlayCSS, 'fsstoredOverlay')
+ .addClass(o.fullscreenClass)
+ ;
+
+ }
+ },
+ fullwindowresize: function(e, evt){
+ overlay.css( o.position(evt) );
+ }
+ })
+ ;
+ });
+ };
+
+ $.fn.videoOverlay.defaults = {
+ video: false,
+ fullscreenClass: 'videooverlay-infullscreen',
+ startCSS: {},
+ position: {}
+ };
+
+ /*
+ * extend jme api
+ */
+ $.multimediaSupport.fn._extend({
+ supportsFullWindow: function(){
+ return supportsFullWindow;
+ },
+ enterFullWindow: function(maxWidth, maxHeight){
+ if(this.visualElem.hasClass('displays-fullscreen') || !supportsFullWindow){return;}
+ var data = $.data(this.element, 'mediaElemSupport'),
+ that = this,
+ curDim = {
+ width: this.visualElem.width(),
+ height: this.visualElem.height()
+ },
+ rel = curDim.width / curDim.height,
+ wrapper = ( data.controlWrapper && data.controlWrapper[0]) ? data.controlWrapper : this.visualElem,
+ vidCss,
+ videoCSS
+ ;
+
+ data._$fullwindowScrollPosition = {
+ top: win.scrollTop(),
+ left: win.scrollLeft()
+ };
+
+ this._posedAncestors = getPosedAncestors(wrapper[0]).storeInlineStyle(parentsCss, 'fsstoredZindexInlineStyle');
+
+ $('html, body')
+ .addClass('contains-fullscreenvideo')
+ .storeInlineStyle(bodyCSS, 'fsstoredInlineStyle')
+ ;
+
+ if(data.controlWrapper && data.controlWrapper[0]){
+ data.controlWrapper.addClass('wraps-fullscreen');
+ }
+
+ windowOverlay.show(wrapper);
+
+ vidCss = getSize(rel, maxWidth, maxHeight);
+ videoCSS= $.extend({}, videoBaseCSS, vidCss);
+
+ this.visualElem
+ .addClass('displays-fullscreen')
+ .storeInlineStyle(videoCSS, 'fsstoredInlineStyle')
+ ;
+
+ doc.bind('keydown.jmefullscreen', function(e){
+ if(e.keyCode === 27){
+ that.exitFullWindow();
+ }
+ });
+ //IE 7 triggers resize event on enterFullWindow
+ setTimeout(function(){
+ win.bind('resize.jmefullscreen', function(){
+ vidCss = getSize(rel, maxWidth, maxHeight);
+ that.visualElem.css(vidCss);
+ $(that.element).triggerHandler('fullwindowresize', vidCss);
+ $(that.element).triggerHandler('resize');
+ });
+ $(that.element).triggerHandler('fullwindowresize', vidCss);
+ }, 0);
+
+ $(this.element).addClass('displays-fullscreen');
+
+ this._trigger({type: 'fullwindow', isFullwindow: true, bbox: vidCss});
+ $(this.element).triggerHandler('fullwindowresize', vidCss);
+ $(this.element).triggerHandler('resize');
+ },
+ exitFullWindow: function(){
+ if(!this.visualElem.hasClass('displays-fullscreen') || !supportsFullWindow){return;}
+ var data = $.data(this.element, 'mediaElemSupport'),
+ that = this,
+ ancestors
+ ;
+ if(this._posedAncestors){
+ this._posedAncestors.storeInlineStyle('fsstoredZindexInlineStyle');
+ }
+
+ $('html, body')
+ .css({overflow: 'auto'})
+ .storeInlineStyle('fsstoredInlineStyle')
+ .removeClass('contains-fullscreenvideo')
+ ;
+
+ this.visualElem
+ .storeInlineStyle('fsstoredInlineStyle')
+ .removeClass('displays-fullscreen')
+ ;
+ if(data.controlWrapper){
+ data.controlWrapper.removeClass('wraps-fullscreen');
+ }
+
+ windowOverlay.hide();
+
+ win.unbind('.jmefullscreen');
+ doc.unbind('.jmefullscreen');
+ $(this.element).removeClass('displays-fullscreen').unbind('.jmefullscreen');
+
+ this._trigger({type: 'fullwindow', isFullwindow: false});
+ $(this.element).triggerHandler('resize');
+ if( data._$fullwindowScrollPosition ){
+ win.scrollTop( data._$fullwindowScrollPosition.top );
+ win.scrollLeft( data._$fullwindowScrollPosition.left );
+ data._$fullwindowScrollPosition = false;
+ }
+ }
+ }, true);
+
+
+ /*
+ * extend jme controls
+ */
+
+ if ( $.fn.jmeControl ) {
+ var supportJmefsButton = $.fn.jmeEmbed.defaults.jwPlayer && $.support.getBoundingClientRect && $.support.cssPointerEvents;
+ if( $.fn.jmeEmbed.defaults.jwPlayer ){
+ $.fn.jmeEmbed.defaults.jwPlayer.plugins.jmefs = $.multimediaSupport.jsPath + 'jmefs.swf';
+ $(function(){
+ var path = ($('script.jme-jwPlayer')[0] || {}).src;
+ if(path){
+ $.fn.jmeEmbed.defaults.jwPlayer.plugins.jmefs = path;
+ }
+ });
+ }
+
+ var fsID = 0,
+ jmefsButton = {
+ create: function(control, video, data, o){
+ if(!supportJmefsButton || !data.controlWrapper || !$.contains(data.controlWrapper[0], control[0])){return;}
+ var that = this,
+ initActive = function(){
+ that.jwPlayer = data.apis.jwPlayer;
+ that.activate();
+ },
+ activate = function(){
+ video
+ .jmeReady(initActive)
+ .one('jmeflashRefresh', initActive)
+ ;
+ }
+ ;
+
+ this.control = control;
+ if(!this.control.attr('id')){
+ fsID++;
+ this.control.attr('id', 'fs-btn-'+ fsID);
+ }
+ this.wrapper = data.controlWrapper;
+ this.video = video;
+ this.data = data;
+ video
+ .bind('apiActivated', function(e, evt){
+ if(evt.api === 'jwPlayer'){
+ activate();
+ }
+ })
+ .bind('apiDeActivated', function(e, evt){
+ if(evt.api === 'jwPlayer'){
+ that.deactivate();
+ }
+ })
+ ;
+ if(data.name === 'jwPlayer'){
+ activate();
+ }
+ },
+ activate: function(){
+ if(!this.jwPlayer.apiElem.jmefsSetButtonCursor || this.activated || this.data.name != 'jwPlayer'){return;}
+ this.activated = true;
+ var that = this,
+ rePos = function(){
+ if(that.timer){
+ clearTimeout(that.timer);
+ }
+ that.timer = setTimeout(function(){
+ that.setPos();
+ }, 30);
+ }
+ ;
+ try{
+ this.jwPlayer.apiElem.jmefsSetButtonCursor(true);
+ } catch(e){return;}
+ this.control.addClass('jme-flashbutton');
+ this.wrapper.addClass('jme-flashbutton-wrapper');
+ if(!this.setBtnCallback){
+ this.jwPlayer.apiElem.jmefsSetButtonCallback('$.fn.jmeControl.defaults.fullscreen.jmeBtn', this.video.attr('id'), this.control.attr('id'));
+ this.setBtnCallback = true;
+ }
+ this.video.bind('resize.jmeFSBtn', rePos);
+ this.wrapper.bind('DOMSubtreeModified.jmeFSBtn', rePos);
+ this.setPos();
+ },
+ deactivate: function(){
+ this.activated = false;
+ this.control.removeClass('jme-flashbutton');
+ this.wrapper.removeClass('jme-flashbutton-wrapper').unbind('DOMSubtreeModified.jmeFSBtn');
+ this.video.unbind('resize.jmeFSBtn');
+ if(this.timer){
+ clearTimeout(this.timer);
+ }
+ if(this.jwPlayer && this.jwPlayer.apiElem && this.jwPlayer.apiElem.jmefsSetButtonSize){
+ try{
+ this.jwPlayer.apiElem.jmefsSetButtonSize(0, 0);
+ this.jwPlayer.apiElem.jmefsSetButtonPosition(-1, -1);
+ } catch(e){return;}
+ }
+ },
+ setPos: function(){
+ if(!this.jwPlayer.isAPIReady || !this.jwPlayer.apiElem.jmefsSetButtonPosition){return;}
+ var displayBBox = this.jwPlayer.apiElem.getBoundingClientRect(),
+ btnBBox = this.control[0].getBoundingClientRect()
+ ;
+ this.jwPlayer.apiElem.jmefsSetButtonPosition(btnBBox.left - displayBBox.left, btnBBox.top - displayBBox.top);
+ this.jwPlayer.apiElem.jmefsSetButtonSize(btnBBox.width, btnBBox.height);
+ }
+ };
+
+
+ $.fn.jmeControl.addControl('video-box', function(control, video, data, o){
+ control.videoOverlay({
+ video: video,
+ startCSS: {
+ width: 'auto',
+ height: 'auto',
+ zIndex: 99998
+ },
+ position: {
+ bottom: 0,
+ left: 0,
+ right: 0,
+ top: 0,
+ wdith: 0,
+ height: 0
+ }
+ });
+ });
+
+ $.fn.jmeControl.addControl('fullscreen', function(control, video, data, o){
+
+ if ( !supportsFullWindow && !video.supportsFullScreen() ) {
+ control.addClass('fullscreen-unsupported ui-disabled');
+ if(data.controlWrapper){
+ data.controlWrapper.addClass('fullscreen-unsupported');
+ }
+ return;
+ }
+ var elems = $.fn.jmeControl.getBtn(control), changeState = function(){
+ if (video.hasClass('displays-fullscreen')) {
+ elems.text.text(elems.names[1]);
+ elems.title.attr('title', elems.titleText[1]);
+ elems.icon.addClass('ui-icon-circle-zoomout').removeClass('ui-icon-circle-zoomin');
+ }
+ else {
+ elems.text.text(elems.names[0]);
+ elems.title.attr('title', elems.titleText[0]);
+ elems.icon.addClass('ui-icon-circle-zoomin').removeClass('ui-icon-circle-zoomout');
+ }
+ };
+ if (o.addThemeRoller) {
+ control.addClass('ui-state-default ui-corner-all');
+ }
+ if(o.fullscreen.tryFullScreen){
+ $.multimediaSupport.beget(jmefsButton).create(control, video, data, o);
+ }
+
+ control.bind('ariaclick', function(){
+ var isFullscreen = video.hasClass('displays-fullscreen');
+ if( !isFullscreen ){
+ video.play();
+ }
+ if ( o.fullscreen.tryFullScreen && !isFullscreen && video.supportsFullScreen() && video.enterFullScreen() ){
+ return;
+ }
+ if ( isFullscreen ) {
+ video.exitFullWindow();
+ } else {
+ video.enterFullWindow(o.fullscreen['max-width'], o.fullscreen['max-height']);
+ }
+
+ return false;
+ });
+ changeState();
+ video.bind('fullwindow', changeState);
+ },
+ {
+ tryFullScreen: true,
+ 'max-width': false,
+ 'max-height': false,
+ jmeBtn: function(type, vid, cid){
+ if(type === 'resize'){
+ $(document.getElementById(vid)).triggerHandler('resize');
+ } else {
+ $(document.getElementById(cid))[(type === 'jmefsButtonOver') ? 'addClass' : 'removeClass']('jme-over ui-state-over');
+ }
+ }
+ });
+
+ }
+})(jQuery);
diff --git a/chimere/static/jme/plugins/playlist.js b/chimere/static/jme/plugins/playlist.js
new file mode 100644
index 0000000..70b5b6d
--- /dev/null
+++ b/chimere/static/jme/plugins/playlist.js
@@ -0,0 +1,301 @@
+/**
+ * playlist plugin for the jMediaelement project | http://github.com/aFarkas/jMediaelement
+ * @author Alexander Farkas
+ * Copyright 2010, Alexander Farkas
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ *
+ * Documentation:
+ * http://protofunc.com/jme/plugins/playlist.html
+ */
+(function($){
+ //helpers for api
+ var split = /\s*\|\s*|\s*\,\s*/g,
+ itemSel = 'li[data-srces], li.play-item',
+ getItemProps = function(item){
+ var props = {
+ label: item.attr('data-label'),
+ srces: []
+ },
+ poster = item.attr('data-poster'),
+ srces = $('a', item),
+ nameElem
+ ;
+
+ if(poster){
+ props.poster = $.multimediaSupport.makeAbsURI(poster);
+ } else {
+ poster = $('img', item)[0];
+ if(poster){
+ props.poster = poster.src;
+ }
+ }
+ if(!props.label){
+ nameElem = $('.item-name', item);
+ props.label = $.trim( ( ( nameElem[0] ) ? nameElem : item ).text() );
+ }
+
+ if( srces.length ){
+ $.each(srces, function(i, src){
+ props.srces[i] = {src: this.href};
+ var type = $.attr(src, 'type');
+ if( type ){
+ props.srces[i].type = type;
+ }
+ });
+
+ } else {
+ props.srces = (item.attr('data-srces') || '').split(split);
+ }
+ return props;
+ },
+ getPlayList = function( elem ){
+ var data = $.data(elem, 'mediaElemSupport');
+ if( !data.playlist ){
+ data.playlist = $([]);
+ }
+ return data;
+ },
+ loadPrevNext = function(api, list, dir, autoplay){
+ var items = $(itemSel, list),
+ index = items.index( items.filter('.ui-state-active') ) + dir
+ ;
+ if( index >= items.length || index < 0 ){
+ if( !list.hasClass('loop') ){return;}
+ if( index >= items.length ){
+ index = 0;
+ } else {
+ index = items.length - 1;
+ }
+ }
+ if ( items[index] ) {
+ list.loadPlaylistItem(items[index], items, autoplay);
+ }
+ },
+ createItemString = function(_i, item){
+ if( !$.isArray(item.srces) ){
+ item.srces = [item.srces];
+ }
+
+ if( typeof item === 'string' ){
+ item = {src: item};
+ }
+
+ var domItem = '<li class="play-item"';
+ if(item.poster){
+ domItem += ' data-poster="'+ item.poster +'"';
+ }
+
+ if( item.name ){
+ domItem += ' data-label="'+ item.name +'"><span class="item-name">'+item.name+'</span>';
+ }
+
+ for(var i = 0, len = item.srces.length; i < len; i++){
+ if(typeof item.srces[i] === 'string'){
+ item.srces[i] = {src: item.srces[i]};
+ }
+ domItem += ' <a href="'+item.srces[i].src +'"';
+
+ if( item.srces[i].type ){
+ domItem += ' type="'+ item.srces[i].type +'"';
+ }
+
+ domItem += '>'+item.srces[i].src +'</a>';
+ }
+
+ domItem += '</li>';
+ return domItem;
+ },
+ createJDOMList = function(list){
+ if(!list.length){return $([]);}
+ //getItemProps,
+ var domList = '<ul class="playlist">';
+ for(var i = 0, len = list.length; i < len; i++){
+ domList += createItemString(i, list[i]);
+ }
+
+ domList += '</ul>';
+
+ return $(domList);
+
+ }
+ ;
+
+ $.each(['activatePlaylist', 'loadPlaylistItem', 'loadNextPlaylistItem', 'loadPreviousPlaylistItem'], function(i, name){
+ var _name = '_'+ name;
+
+ $.fn[name] = function(){
+ var args = Array.prototype.slice.call(arguments, 0);
+ return this.each(function(){
+ var jme = $.data(this, 'playlistFor'),
+ api
+ ;
+ if( jme ){
+ args.unshift(this);
+ api = jme.getJMEAPI();
+ if( name !== 'activatePlaylist' ){
+ api._activatePlaylist.call(api, this);
+ }
+ } else {
+ api = getPlayList(this);
+ args.unshift(api.playlist);
+ api = api.apis[api.name];
+ }
+
+ if( api ){
+ api[_name].apply(api, args);
+ }
+ });
+ };
+ });
+
+ $.multimediaSupport.fn._extend({
+ _activatePlaylist: function(list){
+ list = $(list);
+ var data = getPlayList(this.element);
+ if( data.playlist[0] === list[0] || list.hasClass('active-playlist') ){return;}
+
+ var oldList = data.playlist.removeClass('active-playlist');
+ $(itemSel, data.playlist).removeClass('ui-state-active');
+ if(!list[0]){
+ list = data.playlist;
+ }
+ data.playlist = list;
+ list.addClass('active-playlist');
+
+ // if we have no source, load and play ui-state-active marked or first playlist-item
+ var items = $(itemSel, list),
+ activeItem = items.filter('.ui-state-active')
+ ;
+
+ if( !activeItem[0] ){
+ activeItem = items;
+ }
+
+ this._loadPlaylistItem(list, activeItem[0], items);
+
+ this._trigger({
+ type: 'playlistchange',
+ playlist: list,
+ oldPlaylist: oldList
+ });
+ },
+ _loadPlaylistItem: function(list, item, _items, _autoplay){
+ if(!_items){
+ _items = $(itemSel, list);
+ }
+ _items = $(_items);
+ item = $(item);
+
+ var oldItem = _items
+ .filter('.ui-state-active')
+ .removeClass('ui-state-active'),
+ itemProps = getItemProps(item),
+ curIndex = _items.index( item ),
+ elem = $(this.element),
+ available = {next: true, prev: true}
+ ;
+
+ item.addClass('ui-state-active');
+
+ this.loadSrc(itemProps.srces, itemProps.poster, itemProps.label );
+
+ this._trigger({
+ type: 'playlistitemchange',
+ list: list,
+ items: _items,
+ props: itemProps,
+ currentIndex: curIndex,
+ currentItem: item,
+ previousItem: oldItem,
+ autoplay: _autoplay
+ });
+
+ if( _autoplay ){
+ setTimeout(function(){
+ elem.play();
+ }, 0);
+ }
+ },
+ _loadNextPlaylistItem: function(list, autoplay){
+ loadPrevNext(this, list, 1, autoplay);
+ },
+ _loadPreviousPlaylistItem: function(list, autoplay){
+ loadPrevNext(this, list, -1, autoplay);
+ }
+ });
+
+ $.multimediaSupport.fn._extend({
+ playlist: function(list, _addThemeRoller, activate){
+ var elem = $(this.element);
+ if( !list ){
+ return getPlayList(this.element).playlist;
+ }
+
+ if( $.isArray(list) ){
+ list = createJDOMList( list );
+ } else {
+ list = $( list );
+ }
+
+ if(activate || !$.attr(this.element, 'srces').length ){
+ this._activatePlaylist(list);
+ }
+
+ if( !list.data('playlistFor') ) {
+ var items = $(itemSel, list);
+ elem
+ .bind('ended.playlist', function(){
+ var autoplay = list.hasClass('autoplay-next');
+ if( list.hasClass('active-playlist') && ( autoplay || list.hasClass('autoload-next') ) ){
+ //opera is not responding
+ // ToDo: should delay ended event instead
+ setTimeout(function(){
+ elem.loadNextPlaylistItem(list, autoplay);
+ }, 9);
+ }
+ })
+ ;
+
+ list
+ .delegate(itemSel, 'ariaclick', function(e){
+ list.loadPlaylistItem(this, undefined, true);
+ e.preventDefault();
+ })
+ ;
+
+
+ if(_addThemeRoller){
+ list.addClass('ui-corner-all ui-widget-header');
+ items.addClass('ui-state-default ui-widget-content ui-corner-all');
+ }
+
+ if( !items.attr('role') ){
+ items
+ .attr({
+ role: 'button',
+ tabindex: '0'
+ })
+ .find('a')
+ .attr({
+ role: 'presentation',
+ tabindex: '-1'
+ })
+ ;
+ }
+
+
+ list.data('playlistFor', elem);
+
+ this._trigger({
+ type: 'playlistcreated',
+ playlist: list
+ });
+ }
+ return list;
+ }
+ }, true);
+
+ $.fn.jmeControl.addControl('playlist', function(playlist, element, api, o){
+ element.playlist( playlist, o.addThemeRoller, o.playlist.activate );
+ });
+})(jQuery);
diff --git a/chimere/static/jme/plugins/poster.js b/chimere/static/jme/plugins/poster.js
new file mode 100644
index 0000000..a4c038c
--- /dev/null
+++ b/chimere/static/jme/plugins/poster.js
@@ -0,0 +1,145 @@
+/**
+ * Simple Poster Plugin for jme
+ * @author Matt Dertinger
+ * @version 1.0.0
+ *
+ * http://protofunc.com/jme
+ * http://github.com/aFarkas/jMediaelement
+ *
+ * @description
+ *
+ * HTML:
+ *
+ * <video class="player" preload="none" poster="../media/big-buck-bunny-trailer.png" controls="controls">
+ * ...
+ * </video>
+ *
+ * OR
+ *
+ * <div class="fallback">
+ * <img class="photo" src="../media/big-buck-bunny-trailer.png" alt="" data-enabled="enabled" />
+ * ...
+ * </div>
+ *
+ * API:
+ *
+ * $('video, audio').setPosterAttribute()
+ *
+ * $('video, audio').enablePoster(index|object)
+ *
+ * $('video, audio').disablePoster(index|object)
+ *
+ * Config:
+ *
+ * Documentation:
+ *
+ */
+(function($){
+ //enable posters
+ $(document).bind('jmeEmbed', function(e, data){
+ data = data.data;
+ var mm = $(e.target);
+ mm.setPosterAttribute();
+ if ($.attr(e.target, 'poster')) {
+ data.posterDisplay = $('<img />', {
+ src : $.attr(e.target, 'poster'),
+ "class": "poster-display inactive-poster-display",
+ alt : ""
+ }).insertAfter(e.target);
+ if( data.posterDisplay ){
+ mm.enablePoster(data.posterDisplay, data);
+ }
+ //add fullwindow support
+ if(data.posterDisplay.videoOverlay && mm.is('video')){
+ data.posterDisplay
+ .videoOverlay({
+ fullscreenClass: 'poster-in-fullscreen',
+ video: mm,
+ startCSS: {
+ width: 'auto',
+ zIndex: 99999
+ },
+ position: {
+ bottom: 0,
+ left: 0,
+ right: 0
+ }
+ })
+ ;
+ }
+ mm
+ .bind('play', function(){
+ mm.disablePoster(data.posterDisplay, data);
+ })
+ .bind('ended', function(){
+ mm.enablePoster(data.posterDisplay, data);
+ //worarkound:
+ mm.pause();
+ })
+ ;
+ }
+ });
+
+ /*
+ * extend jme api
+ */
+ $.multimediaSupport.fn._extend({
+ positionPoster: function(object, _data){
+ object = (isFinite(object)) ? posters.filter(':eq('+ object +')') : $(object);
+ if( !_data ){
+ _data = $.data(this.element, 'mediaElemSupport');
+ }
+ // Only if the poster is visible
+ if (!_data.posterDisplay || _data.posterDisplay.is(":hidden")) { return; }
+ _data.posterDisplay.height($(this.element).height() + "px"); // Need incase controlsBelow
+ _data.posterDisplay.width($(this.element).width() + "px"); // Could probably do 100% of box
+ },
+ disablePoster: function(object, _data){
+ object = (isFinite(object)) ? posters.filter(':eq('+ object +')') : $(object);
+ if( !_data ){
+ _data = $.data(this.element, 'mediaElemSupport');
+ }
+ object.removeAttr('data-enabled');
+ _data.posterDisplay.addClass('inactive-poster-display').fadeOut('slow');
+ },
+ enablePoster: function(object, _data){
+ var posters = $('img.poster-display', this.element),
+ that = this,
+ mm = $(this.element),
+ posterData,
+ found
+ ;
+
+ if( !_data ){
+ _data = mm.data('mediaElemSupport');
+ }
+ object = (isFinite(object)) ? posters.filter(':eq('+ object +')') : $(object);
+ posters
+ .filter('[data-enabled]')
+ .each(function(){
+ if(this !== object[0]){
+ that.disablePoster(this, _data);
+ }
+ })
+ ;
+ if (!object[0]) { return; }
+
+ posterData = $.data(object[0], 'jmePoster') || $.data(object[0], 'jmePoster', {load: false});
+ posterData.posterDisplay = _data.posterDisplay;
+ posterData.posterDisplay.removeClass('inactive-poster-display').fadeIn("slow");
+ // We may not need this. But if we do, we should make it respect config.
+ /* if (this.options.fit) {
+ that.positionPoster(this, _data);
+ } */
+ object.attr('data-enabled', 'enabled');
+
+ },
+ setPosterAttribute: function() {
+ if (!$.attr(this.element, 'poster')) {
+ var image = $('img.photo[data-enabled]', this.element).first();
+ if (image) { $.attr(this.element, 'poster', image.attr('src')); }
+ }
+ }
+ }, true);
+
+})(jQuery);
diff --git a/chimere/static/jme/plugins/timerange.js b/chimere/static/jme/plugins/timerange.js
new file mode 100644
index 0000000..e01352b
--- /dev/null
+++ b/chimere/static/jme/plugins/timerange.js
@@ -0,0 +1,165 @@
+/**
+ * timerange plugin for the jMediaelement project | http://github.com/aFarkas/jMediaelement
+ * @author Alexander Farkas
+ * Copyright 2010, Alexander Farkas
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ *
+ *
+ * $('video').addTimeRange('timeRangeID-1', {
+ * enter: 1,
+ * leave: 12,
+ * callback:function(e){
+ * console.log(e);
+ * }
+ * }
+ * );
+ *
+ * $('video').addTimeRange('timeRangeID-1', {
+ * enter: 23,
+ * leave: 26
+ * }
+ * );
+ *
+ * $('video').addTimeRange('timeRangeID-2', {
+ * enter: 3,
+ * leave: 21
+ * }
+ * );
+ *
+ * $('video').addTimeRange('timeRangeID-2', {
+ * enter: 25,
+ * leave: 31,
+ * callback:function(e){
+ * console.log(e);
+ * }
+ * }
+ * );
+ */
+(function($){
+ function isBetweenRange(elem, timerange, time){
+ if(!timerange.active){return;}
+
+ var e = {time: time};
+
+ if(!timerange.entered){
+ var i = timerange.lastIndex,
+ len = timerange.enterRanges.length,
+ createEvent = function(index){
+ e.rangeEnter = timerange.enterRanges[index];
+ e.rangeLeave = timerange.leaveRanges[index];
+ e.rangeIndex = index;
+ timerange.lastIndex = e.rangeIndex;
+ timerange.lastTime = timerange.enterRanges[index];
+ e.type = 'rangeenter';
+ timerange.entered = [ e.rangeEnter, e.rangeLeave, e.rangeIndex ];
+ }
+ ;
+ if(timerange.lastTime > time){
+ while(i--){
+ if(timerange.enterRanges[i] <= time && timerange.leaveRanges[i] >= time){
+ createEvent(i);
+ break;
+ } else if(timerange.leaveRanges[i] < time){
+ timerange.lastIndex = i;
+ timerange.lastTime = timerange.enterRanges[i];
+ break;
+ }
+ }
+ } else {
+ for(; i < len; i++){
+ if(timerange.enterRanges[i] <= time && timerange.leaveRanges[i] >= time){
+ createEvent(i);
+ break;
+ } else if(timerange.leaveRanges[i] > time){
+ if(timerange.enterRanges[i] < time){
+ timerange.lastIndex = i;
+ timerange.lastTime = timerange.leaveRanges[i];
+ }
+ break;
+ }
+ }
+ }
+ } else if(time < timerange.entered[0] || timerange.entered[1] < time){
+ e.rangeEnter = timerange.entered[0];
+ e.rangeLeave = timerange.entered[1];
+ e.rangeIndex = timerange.entered[2];
+ e.type = 'rangeleave';
+ timerange.entered = false;
+ }
+ if(e.type){
+ if(timerange.callback){
+ timerange.callback.call(elem, e );
+ }
+ $(elem).triggerHandler(e);
+ }
+
+ }
+
+ var numsort = function(a, b) {
+ return a - b;
+ };
+
+ $.fn.addTimeRange = function(name, o){
+ if(typeof o === 'boolean'){
+ o = {activate: o};
+ }
+
+ o = $.extend({}, $.fn.addTimeRange.defaults, o);
+
+ return this.each(function(){
+ var api = $.data(this, 'mediaElemSupport');
+ if(!api){
+ return;
+ }
+ if(!api.timeRanges){
+ api.timeRanges = {};
+ }
+
+ if(!api.timeRanges[name]){
+ api.timeRanges[name] = {
+ enterRanges: [],
+ leaveRanges: [],
+ lastIndex: 0,
+ lastTime: 0,
+ entered: false,
+ active: false,
+ callback: o.callback
+ };
+ }
+
+ if(o.callback){
+ api.timeRanges[name].callback = o.callback;
+ }
+ if( typeof o.enter !== 'boolean' && isFinite(o.enter) && typeof o.leave !== 'boolean' && isFinite(o.leave) ) {
+ api.timeRanges[name].enterRanges.push(o.enter);
+ api.timeRanges[name].leaveRanges.push(o.leave);
+ }
+
+ if(o.activate && !api.timeRanges[name].active){
+ api.timeRanges[name].active = true;
+ $(this).bind('timechange.'+name, function(e, evt){
+ isBetweenRange(this, api.timeRanges[name], evt.time);
+ });
+ } else if(!o.activate && api.timeRanges[name].active){
+ api.timeRanges[name].active = false;
+ api.timeRanges[name].entered = false;
+ $(this).unbind('timechange.'+ name);
+ }
+
+
+ if(o.resort){
+ api.timeRanges[name].enterRanges.sort(numsort);
+ api.timeRanges[name].leaveRanges.sort(numsort);
+ }
+
+ });
+ };
+
+ $.fn.addTimeRange.defaults = {
+ enter: false,
+ leave: false,
+ callback: false,
+ resort: false,
+ activate: true
+ };
+})(jQuery);
diff --git a/chimere/static/jme/plugins/track.js b/chimere/static/jme/plugins/track.js
new file mode 100644
index 0000000..742fce4
--- /dev/null
+++ b/chimere/static/jme/plugins/track.js
@@ -0,0 +1,403 @@
+/**
+ * Simple Caption Plugin for jme
+ * @version 1.0
+ *
+ * http://protofunc.com/jme
+ * http://github.com/aFarkas/jMediaelement
+ *
+ * -------------------
+ * Uses a modified Version of Silvia Pfeifers srt-parser
+ * http://www.annodex.net/~silvia/itext/
+ * -------------------
+ *
+ * @description
+ *
+ * HTML:
+ * <a class="track" href="srtfile.srt" lang="en" data-enabled="enabled" data-sanitize="sanitize" data-role="textaudiodesc">name</a>
+ * <a class="track" href="caption-dfxp.xml" type="application/ttaf+xml" data-enabled="enabled">name</a>
+ *
+ * API:
+ *
+ * $('video, audio').getTrackContent(index|object, callback)
+ *
+ * $('video, audio').enableTrack(index|object)
+ *
+ * $('video, audio').disableTrack(index|object)
+ *
+ *
+ * HTML-Display-Area:
+ * <video></video>
+ * <div class="track-display">
+ * <div>Text</div>
+ * </div>
+ * and
+ * <div class="track-display tad-track" aria-live="assertive" style="position: absolute; left: -9999em; width: 5px; height: 5px; overflow: hidden; z-index: -100;">
+ * <div>Text</div>
+ * </div>
+ *
+ * <video></video>
+ * <div class="track-display inactive-track-display"></div>
+ * and
+ * <div class="track-display tad-track inactive-track-display" aria-live="assertive" style="position: absolute; left: -9999em; width: 5px; height: 5px; overflow: hidden; z-index: -100;"></div>
+ *
+ *
+ * HTML-UI:
+ * only toggles first track on/off. for more functionality script your own UI. API is powerfull enough
+ * <a class="toggle-track">toggle track</a>
+ */
+
+(function($){
+
+ //enable tracks
+ $(document).bind('jmeEmbed', function(e, data){
+ data = data.data;
+ var mm = $(e.target),
+ dir = ( mm.css('direction') === 'rtl' ) ? 'right' : 'left',
+ activeTracks = $('a.track[data-enabled]', mm)
+ ;
+ data.trackDisplay = $('<div class="track-display inactive-track-display" style="display: none;"></div>').insertAfter(e.target);
+ data.tadDisplay = $('<div class="track-display tad-track inactive-track-display" aria-live="assertive" style="display: none; position: absolute; '+ dir +': -9999em; width: 5px; height: 5px; overflow: hidden; z-index: -100;"></div>').insertAfter(e.target);
+ data.trackDisplays = data.trackDisplay.add(data.tadDisplay);
+ if( activeTracks[0] ){
+ mm.enableTrack(activeTracks[0], data);
+ }
+ //add fullwindow support
+ if(data.trackDisplay.videoOverlay && mm.is('video')){
+ data.trackDisplay
+ .videoOverlay({
+ fullscreenClass: 'track-in-fullscreen',
+ video: mm,
+ startCSS: {
+ width: 'auto'
+ },
+ position: {
+ bottom: 0,
+ left: 0,
+ right: 0
+ }
+ })
+ ;
+ }
+ });
+
+ /*
+ * extend the api
+ */
+ var capTypes = {
+ 'text/srt': ['text', 'parseSrt'],
+ 'application/x-srt': ['text', 'parseSrt'],
+ 'application/ttaf+xml': ['xml', 'parseDfxp']
+ };
+ $.multimediaSupport.fn._extend({
+ disableTrack: function(object, _data){
+ object = (isFinite(object)) ? tracks.filter(':eq('+ object +')') : $(object);
+ if( !_data ){
+ _data = $.data(this.element, 'mediaElemSupport');
+ }
+ object.removeAttr('data-enabled');
+ $(this.element).addTimeRange(object[0].href, false);
+ _data.trackDisplays.addClass('inactive-track-display').hide().empty();
+ this._trigger('trackChange', {track: object, enabled: false});
+ },
+ getTrackContent: function(object, fn, _trackData){
+ object = (isFinite(object)) ? $('a.track', this.element).filter(':eq('+ object +')') : $(object);
+ _trackData = _trackData || $.data(object[0], 'jmeTrack') || $.data(object[0], 'jmeTrack', {load: false});
+ if( !_trackData.load ){
+ _trackData.load = 'loading';
+ var type = object.attr('type') || 'text/srt';
+ type = capTypes[type];
+ if(!type){
+ setTimeout( function(){
+ throw("we don't know. captions type: "+ type);
+ }, 0);
+ return;
+ }
+
+ $.ajax({
+ url: object[0].href,
+ dataType: type[0],
+ success: function(srt){
+ _trackData.load = 'loaded';
+ $[type[1]](
+ srt,
+ function(caps){
+ _trackData.captions = caps;
+ fn( caps );
+ },
+ (object[0].attributes['data-sanitize'] || {}).specified
+ );
+ }
+ });
+ } else {
+ fn(trackData.captions);
+ }
+ },
+ enableTrack: function(object, _data){
+ var tracks = $('a.track', this.element),
+ that = this,
+ mm = $(this.element),
+ trackData,
+ found
+ ;
+ if( !_data ){
+ _data = mm.data('mediaElemSupport');
+ }
+ object = (isFinite(object)) ? tracks.filter(':eq('+ object +')') : $(object);
+
+ tracks
+ .filter('[data-enabled]')
+ .each(function(){
+ if(this !== object[0]){
+ that.disableTrack(this, _data);
+ }
+ })
+ ;
+ if( !object[0] ){return;}
+
+ trackData = $.data(object[0], 'jmeTrack') || $.data(object[0], 'jmeTrack', {load: false});
+ trackData.trackDisplay = ( object.is('[data-role=textaudiodesc]') ) ? _data.tadDisplay : _data.trackDisplay;
+ trackData.trackDisplay.removeClass('inactive-track-display').show();
+ if( !trackData.load ){
+ this.getTrackContent(object,
+ function(){
+ var captionChange = function (e){
+ e.target = mm[0];
+ e = $.extend({}, e, {
+ target: mm[0],
+ captions: trackData.captions,
+ caption: trackData.captions[e.rangeIndex],
+ type: (e.type === 'rangeenter') ? 'showCaption' : 'hideCaption'
+ });
+ if( e.type === 'showCaption' ){
+ trackData.trackDisplay.html( '<div>'+ e.caption.content +'</div>' );
+ } else {
+ trackData.trackDisplay[0].innerHTML = '';
+ }
+ mm.triggerHandler(e.type, e);
+ };
+ $.each(trackData.captions, function(i, caption){
+ mm.addTimeRange(object[0].href, {
+ enter: caption.start,
+ leave: caption.end,
+ callback: captionChange,
+ activate: true
+ });
+ });
+ },
+ trackData
+ );
+ } else {
+ mm.addTimeRange(object[0].href, true);
+ }
+ object.attr('data-enabled', 'enabled');
+ this._trigger('trackChange', {track: object, enabled: true, trackData: trackData});
+ }
+ }, true);
+
+ /*
+ * extend jme controls
+ */
+
+ $.fn.jmeControl.addControl('toggle-track', function(control, mm, data, o){
+ var elems = $.fn.jmeControl.getBtn(control),
+ tracks = $('a.track', this.element),
+ changeState = function(){
+ var enabled = tracks.filter('[data-enabled]');
+ if( enabled[0] ){
+ elems.text.text(elems.names[1]);
+ elems.title.attr('title', elems.titleText[1]);
+ elems.icon
+ .addClass('ui-icon-document')
+ .removeClass('ui-icon-document-b')
+ ;
+ } else {
+ elems.text.text(elems.names[0]);
+ elems.title.attr('title', elems.titleText[0]);
+ elems.icon
+ .addClass('ui-icon-document-b')
+ .removeClass('ui-icon-document')
+ ;
+ }
+ }
+ ;
+
+ if(o.addThemeRoller){
+ control.addClass('ui-state-default ui-corner-all');
+ }
+ if( !tracks[0] ){
+ control.addClass(o.classPrefix +'no-track');
+ }
+ control
+ .bind('ariaclick', function(){
+ var enabled = tracks.filter('[data-enabled]');
+ if(enabled[0]){
+ mm.disableTrack(enabled);
+ } else if( tracks[0] ) {
+ mm.enableTrack(tracks[0]);
+ }
+ return false;
+ })
+ ;
+ changeState();
+ mm.bind('trackChange', changeState);
+ });
+
+$.backgroundEach = function(arr, processFn, completeFn){
+ var i = 0,
+ l = arr.length
+ ;
+ var process = function(){
+ var start = new Date().getTime();
+ for(; i < l; i++){
+ processFn(i, arr[i], arr);
+ if(new Date().getTime() - start > 100){
+ setTimeout(process, 50);
+ break;
+ }
+ }
+ if( i >= l - 1 ){
+ completeFn(arr, i, l);
+ }
+ };
+ process();
+};
+$.parseDfxp = (function(){
+ var sanitizeReg = /<[a-zA-Z\/][^>]*>/g;
+ var getTime = function(time){
+ time = (time || '').split(':');
+ if(time.length === 3){
+ time = (parseInt(time[0], 10) * 60 * 60) +
+ (parseInt(time[1], 10) * 60) +
+ (parseInt(time[2], 10))
+ ;
+ return isNaN(time) ? false : time;
+ }
+ return false;
+ },
+ doc = document,
+ allowedNodes = {
+ span: 1,
+ div: 1,
+ p: 1,
+ em: 1,
+ strong: 1,
+ br: 1
+ },
+ getContent = function(elem){
+ var childs = elem.childNodes,
+ div = doc.createElement('div'),
+ childElem, childContent
+ ;
+
+ for(var i = 0, len = childs.length; i < len; i++){
+ if(childs[i].nodeType === 3){
+ div.appendChild( doc.createTextNode(childs[i].data) );
+ } else if(childs[i].nodeType === 1 && allowedNodes[childs[i].nodeName.toLowerCase()]){
+ childElem = doc.createElement(childs[i].nodeName);
+ childContent = getContent(childs[i]);
+ if(childContent){
+ childElem.innerHTML = childContent;
+ }
+ div.appendChild( childElem );
+ }
+
+ }
+ return div.innerHTML;
+ }
+ ;
+
+
+ return function(xml, complete, sanitize){
+ var caps = $('p, div, span', xml).filter('[begin][end]'),
+ captions = []
+ ;
+ var e, s, c;
+ $.backgroundEach(caps, function(i){
+ s = getTime(caps[i].getAttribute('begin'));
+ e = getTime(caps[i].getAttribute('end'));
+
+ if(s !== false && e !== false){
+ c = getContent(caps[i]) || '';
+ captions.push({content: c, start: s, end: e});
+ }
+ }, function(){
+ complete(captions);
+ });
+ };
+})();
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML5 video itext demonstration code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Silvia Pfeiffer <silvia@siliva-pfeiffer.de>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// SRT specification from http://forum.doom9.org/archive/index.php/t-73953.html
+// but without the formatting, which is just interpreted as text
+
+// Function to parse srt file
+var regs = {
+ sanitize: /<[a-zA-Z\/][^>]*>/g,
+ dosLines: /\r+/g,
+ index: /^\d+$/,
+ time: /(\d+):(\d+):(\d+)(?:,(\d+))?\s*--?>\s*(\d+):(\d+):(\d+)(?:,(\d+))?/
+
+};
+$.parseSrt = function(srt, complete, sanitize) {
+ srt = srt.replace(regs.dosLines, ''); // remove dos newlines
+ srt = $.trim(srt); // trim white space start and end
+ if(sanitize){
+ srt = srt.replace(regs.sanitize, ''); // remove all html tags for security reasons
+ }
+
+ // get captions
+ var captions = [];
+ var caplist = srt.split('\n\n');
+ $.backgroundEach(caplist, function(i){
+ var caption = "";
+ var content, start, end, s;
+ caption = caplist[i];
+ s = caption.split(/\n/);
+ if (s[0].match(regs.index) && s[1]) {
+ // ignore caption number in s[0]
+ // parse time string
+ var m = s[1].match(regs.time);
+ if (m) {
+ start =
+ (parseInt(m[1], 10) * 60 * 60) +
+ (parseInt(m[2], 10) * 60) +
+ (parseInt(m[3], 10)) +
+ (parseInt(m[4], 10) / 1000);
+ end =
+ (parseInt(m[5], 10) * 60 * 60) +
+ (parseInt(m[6], 10) * 60) +
+ (parseInt(m[7], 10)) +
+ (parseInt(m[8], 10) / 1000);
+ content = s.slice(2).join("<br>");
+ captions.push({start: start, end: end, content: content});
+ }
+ }
+
+ }, function(){
+ complete(captions);
+ });
+};
+})(jQuery);
diff --git a/chimere/static/jme/plugins/ui.sounds.js b/chimere/static/jme/plugins/ui.sounds.js
new file mode 100644
index 0000000..1ec4a78
--- /dev/null
+++ b/chimere/static/jme/plugins/ui.sounds.js
@@ -0,0 +1,69 @@
+(function($){
+
+ var $m = $.multimediaSupport,
+ bgWrapper = $('<div class="jme-bg-wrapper" style="position: absolute; overflow: hidden;display: block; width: 10px; height: 10px;" />'),
+ appended = false
+ ;
+
+ bgWrapper.css( ($('html').css('dir') === 'rtl') ? 'right' : 'left', '-99999px' );
+
+ $m.createBGSound = function(mediasrces, embedOpts){
+ if( !appended ){
+ bgWrapper
+ .appendTo(document.documentElement)
+ .bind('play playing loadedmeta pause waiting ended mediareset mute volumelevelchange', function(e){
+ e.stopPropagation();
+ })
+ ;
+ appended = true;
+ }
+
+ var audio = $( $.fixHTML5('<audio style="display: block; width: 10px; height: 10px;" role="presentation" tabindex="-1" preload="auto" />') )
+ .appendTo(bgWrapper)
+ .attr('srces', mediasrces)
+ .jmeEmbed(embedOpts)
+ ;
+
+ return audio;
+ };
+ var _createWidget = $.Widget.prototype._createWidget;
+
+
+ $.extend(true, $.Widget.prototype, {
+ options: {sound: {}, soundEmbed: {}},
+ _createWidget: function(){
+ var ret = _createWidget.apply(this, arguments);
+ this._createSound();
+ return ret;
+ },
+ _soundAPI: {},
+ _createSound: function(){
+ var o = this.options,
+ element = this.element,
+ that = this
+ ;
+ $.each(o.sound || {}, function(type, mediasrces){
+ type = ( type === that.widgetEventPrefix ?
+ type :
+ that.widgetEventPrefix + type ).toLowerCase();
+ that._soundAPI[type] = $m.createBGSound(mediasrces, o.soundEmbed || {});
+ element.bind(type, function(){
+ that._soundAPI[type].stopAndPlay();
+ });
+ });
+ }//,
+ /* todo:
+ option: function(){},
+ destroy: function(){}
+ */
+
+ });
+
+ $.multimediaSupport.fn._extend({
+ stopAndPlay: function(){
+ this.currentTime(0);
+ this.play();
+ }
+ });
+
+})(jQuery);