text: /*!
   * MediaElementPlayer
   * http://mediaelementjs.com/
   *
   * Creates a controller bar for HTML5 <video> add <audio> tags
   * using jQuery and MediaElement.js (HTML5 Flash/Silverlight wrapper)
   *
   * Copyright 2010-2012, John Dyer (http://j.hn/)
   * Dual licensed under the MIT or GPL Version 2 licenses.
   *
   */
  if (typeof jQuery != 'undefined') {
  	mejs.$ = jQuery;
  } else if (typeof ender != 'undefined') {
  	mejs.$ = ender;
  }
  (function ($) {
  
  	// default player values
  	mejs.MepDefaults = {
  		// url to poster (to fix iOS 3.x)
  		poster: '',
  		// default if the <video width> is not specified
  		defaultVideoWidth: 480,
  		// default if the <video height> is not specified
  		defaultVideoHeight: 270,
  		// if set, overrides <video width>
  		videoWidth: -1,
  		// if set, overrides <video height>
  		videoHeight: -1,
  		// default if the user doesn't specify
  		defaultAudioWidth: 400,
  		// default if the user doesn't specify
  		defaultAudioHeight: 30,
  
  		// default amount to move back when back key is pressed		
  		defaultSeekBackwardInterval: function(media) {
  			return (media.duration * 0.05);
  		},		
  		// default amount to move forward when forward key is pressed				
  		defaultSeekForwardInterval: function(media) {
  			return (media.duration * 0.05);
  		},		
  		
  		// width of audio player
  		audioWidth: -1,
  		// height of audio player
  		audioHeight: -1,		
  		// initial volume when the player starts (overrided by user cookie)
  		startVolume: 0.8,
  		// useful for <audio> player loops
  		loop: false,
  		// resize to media dimensions
  		enableAutosize: true,
  		// forces the hour marker (##:00:00)
  		alwaysShowHours: false,
  
  		// show framecount in timecode (##:00:00:00)
  		showTimecodeFrameCount: false,
  		// used when showTimecodeFrameCount is set to true
  		framesPerSecond: 25,
  		
  		// automatically calculate the width of the progress bar based on the sizes of other elements
  		autosizeProgress : true,
  		// Hide controls when playing and mouse is not over the video
  		alwaysShowControls: false,
  		// force iPad's native controls
  		iPadUseNativeControls: false,
  		// force iPhone's native controls
  		iPhoneUseNativeControls: false,	
  		// force Android's native controls
  		AndroidUseNativeControls: false,			
  		// features to show
  		features: ['playpause','current','progress','duration','tracks','volume','fullscreen'],
  		// only for dynamic
  		isVideo: true,
  		
  		// turns keyboard support on and off for this instance
  		enableKeyboard: true,
  		
  		// whenthis player starts, it will pause other players
  		pauseOtherPlayers: true,
  		
  		// array of keyboard actions such as play pause
  		keyActions: [
  				{
  						keys: [
  								32, // SPACE
  								179 // GOOGLE play/pause button
  							  ],
  						action: function(player, media) {
  								if (media.paused || media.ended) {
  										media.play();	
  								} else {
  										media.pause();
  								}										
  						}
  				},
  				{
  						keys: [38], // UP
  						action: function(player, media) {
  								var newVolume = Math.min(media.volume + 0.1, 1);
  								media.setVolume(newVolume);
  						}
  				},
  				{
  						keys: [40], // DOWN
  						action: function(player, media) {
  								var newVolume = Math.max(media.volume - 0.1, 0);
  								media.setVolume(newVolume);
  						}
  				},
  				{
  						keys: [
  								37, // LEFT
  								227 // Google TV rewind
  						],
  						action: function(player, media) {
  								if (!isNaN(media.duration) && media.duration > 0) {
  										if (player.isVideo) {
  												player.showControls();
  												player.startControlsTimer();
  										}
  										
  										// 5%
  										var newTime = Math.max(media.currentTime - player.options.defaultSeekBackwardInterval(media), 0);
  										media.setCurrentTime(newTime);
  								}
  						}
  				},
  				{
  						keys: [
  								39, // RIGHT
  								228 // Google TV forward
  						], 
  						action: function(player, media) {
  								if (!isNaN(media.duration) && media.duration > 0) {
  										if (player.isVideo) {
  												player.showControls();
  												player.startControlsTimer();
  										}
  										
  										// 5%
  										var newTime = Math.min(media.currentTime + player.options.defaultSeekForwardInterval(media), media.duration);										
  										media.setCurrentTime(newTime);
  								}
  						}
  				},
  				{
  						keys: [70], // f
  						action: function(player, media) {
  								if (typeof player.enterFullScreen != 'undefined') {
  										if (player.isFullScreen) {
  												player.exitFullScreen();
  										} else {
  												player.enterFullScreen();
  										}
  								}
  						}
  				}					
  		]		
  	};
  
  	mejs.mepIndex = 0;
  	
  	mejs.players = [];
  
  	// wraps a MediaElement object in player controls
  	mejs.MediaElementPlayer = function(node, o) {
  		// enforce object, even without "new" (via John Resig)
  		if ( !(this instanceof mejs.MediaElementPlayer) ) {
  			return new mejs.MediaElementPlayer(node, o);
  		} 
  
  		var t = this;
  		
  		// these will be reset after the MediaElement.success fires
  		t.$media = t.$node = $(node);
  		t.node = t.media = t.$media[0];		
  		
  		// check for existing player
  		if (typeof t.node.player != 'undefined') {
  			return t.node.player;
  		} else {
  			// attach player to DOM node for reference
  			t.node.player = t;
  		}
  				
  				
  		// try to get options from data-mejsoptions
  		if (typeof o == 'undefined') {
  			o = t.$node.data('mejsoptions');	
  		}
  			
  		// extend default options
  		t.options = $.extend({},mejs.MepDefaults,o);
  		
  		// add to player array (for focus events)
  		mejs.players.push(t);
  		
  		// start up
  		t.init();
  
  		return t;
  	};
  
  	// actual player
  	mejs.MediaElementPlayer.prototype = {
  		
  		hasFocus: false,
  		
  		controlsAreVisible: true,
  		
  		init: function() {
  
  			var
  				t = this,
  				mf = mejs.MediaFeatures,
  				// options for MediaElement (shim)
  				meOptions = $.extend(true, {}, t.options, {
  					success: function(media, domNode) { t.meReady(media, domNode); },
  					error: function(e) { t.handleError(e);}
  				}),
  				tagName = t.media.tagName.toLowerCase();
  		
  			t.isDynamic = (tagName !== 'audio' && tagName !== 'video');
  			
  			if (t.isDynamic) {	
  				// get video from src or href?				
  				t.isVideo = t.options.isVideo;						
  			} else {
  				t.isVideo = (tagName !== 'audio' && t.options.isVideo);
  			}
  		
  			// use native controls in iPad, iPhone, and Android	
  			if ((mf.isiPad && t.options.iPadUseNativeControls) || (mf.isiPhone && t.options.iPhoneUseNativeControls)) {
  				
  				// add controls and stop
  				t.$media.attr('controls', 'controls');
  
  				// attempt to fix iOS 3 bug
  				//t.$media.removeAttr('poster');
                                  // no Issue found on iOS3 -ttroxell
  
  				// override Apple's autoplay override for iPads
  				if (mf.isiPad && t.media.getAttribute('autoplay') !== null) {
  					t.media.load();
  					t.media.play();
  				}
  					
  			} else if (mf.isAndroid && t.AndroidUseNativeControls) {
  				
  				// leave default player
  
  			} else {
  
  				// DESKTOP: use MediaElementPlayer controls
  				
  				// remove native controls 			
  				t.$media.removeAttr('controls');					
  				
  				// unique ID
  				t.id = 'mep_' + mejs.mepIndex++;
  
  				// build container
  				t.container =
  					$('<div id="' + t.id + '" class="mejs-container">'+
  						'<div class="mejs-inner">'+
  							'<div class="mejs-mediaelement"></div>'+
  							'<div class="mejs-layers"></div>'+
  							'<div class="mejs-controls"></div>'+
  							'<div class="mejs-clear"></div>'+
  						'</div>' +
  					'</div>')
  					.addClass(t.$media[0].className)
  					.insertBefore(t.$media);	
  					
  				// add classes for user and content
  				t.container.addClass(
  					(mf.isAndroid ? 'mejs-android ' : '') +
  					(mf.isiOS ? 'mejs-ios ' : '') +
  					(mf.isiPad ? 'mejs-ipad ' : '') +
  					(mf.isiPhone ? 'mejs-iphone ' : '') +
  					(t.isVideo ? 'mejs-video ' : 'mejs-audio ')
  				);	
  					
  
  				// move the <video/video> tag into the right spot
  				if (mf.isiOS) {
  				
  					// sadly, you can't move nodes in iOS, so we have to destroy and recreate it!
  					var $newMedia = t.$media.clone();
  					
  					t.container.find('.mejs-mediaelement').append($newMedia);
  					
  					t.$media.remove();
  					t.$node = t.$media = $newMedia;
  					t.node = t.media = $newMedia[0]
  					
  				} else {
  					
  					// normal way of moving it into place (doesn't work on iOS)
  					t.container.find('.mejs-mediaelement').append(t.$media);
  				}
  				
  				// find parts
  				t.controls = t.container.find('.mejs-controls');
  				t.layers = t.container.find('.mejs-layers');
  
  				// determine the size
  				
  				/* size priority:
  					(1) videoWidth (forced), 
  					(2) style="width;height;"
  					(3) width attribute,
  					(4) defaultVideoWidth (for unspecified cases)
  				*/
  				
  				var tagType = (t.isVideo ? 'video' : 'audio'),
  					capsTagName = tagType.substring(0,1).toUpperCase() + tagType.substring(1);
  					
  				
  				if (t.options[tagType + 'Width'] > 0 || t.options[tagType + 'Width'].toString().indexOf('%') > -1) {
  					t.width = t.options[tagType + 'Width'];
  				} else if (t.media.style.width !== '' && t.media.style.width !== null) {
  					t.width = t.media.style.width;						
  				} else if (t.media.getAttribute('width') !== null) {
  					t.width = t.$media.attr('width');
  				} else {
  					t.width = t.options['default' + capsTagName + 'Width'];
  				}
  				
  				if (t.options[tagType + 'Height'] > 0 || t.options[tagType + 'Height'].toString().indexOf('%') > -1) {
  					t.height = t.options[tagType + 'Height'];
  				} else if (t.media.style.height !== '' && t.media.style.height !== null) {
  					t.height = t.media.style.height;
  				} else if (t.$media[0].getAttribute('height') !== null) {
  					t.height = t.$media.attr('height');	
  				} else {
  					t.height = t.options['default' + capsTagName + 'Height'];
  				}
  
  				// set the size, while we wait for the plugins to load below
  				t.setPlayerSize(t.width, t.height);
  				
  				// create MediaElementShim
  				meOptions.pluginWidth = t.height;
  				meOptions.pluginHeight = t.width;				
  			}
  			
  			
  
  			// create MediaElement shim
  			mejs.MediaElement(t.$media[0], meOptions);
  		},
  		
  		showControls: function(doAnimation) {
  			var t = this;
  			
  			doAnimation = typeof doAnimation == 'undefined' || doAnimation;
  			
  			if (t.controlsAreVisible)
  				return;
  			
  			if (doAnimation) {
  				t.controls
  					.css('visibility','visible')
  					.stop(true, true).fadeIn(200, function() {t.controlsAreVisible = true;});	
  	
  				// any additional controls people might add and want to hide
  				t.container.find('.mejs-control')
  					.css('visibility','visible')
  					.stop(true, true).fadeIn(200, function() {t.controlsAreVisible = true;});	
  					
  			} else {
  				t.controls
  					.css('visibility','visible')
  					.css('display','block');
  	
  				// any additional controls people might add and want to hide
  				t.container.find('.mejs-control')
  					.css('visibility','visible')
  					.css('display','block');
  					
  				t.controlsAreVisible = true;
  			}
  			
  			t.setControlsSize();
  			
  		},
  
  		hideControls: function(doAnimation) {
  			var t = this;
  			
  			doAnimation = typeof doAnimation == 'undefined' || doAnimation;
  			
  			if (!t.controlsAreVisible)
  				return;
  			
  			if (doAnimation) {
  				// fade out main controls
  				t.controls.stop(true, true).fadeOut(200, function() {
  					$(this)
  						.css('visibility','hidden')
  						.css('display','block');
  						
  					t.controlsAreVisible = false;
  				});	
  	
  				// any additional controls people might add and want to hide
  				t.container.find('.mejs-control').stop(true, true).fadeOut(200, function() {
  					$(this)
  						.css('visibility','hidden')
  						.css('display','block');
  				});	
  			} else {
  				
  				// hide main controls
  				t.controls
  					.css('visibility','hidden')
  					.css('display','block');		
  				
  				// hide others
  				t.container.find('.mejs-control')
  					.css('visibility','hidden')
  					.css('display','block');
  					
  				t.controlsAreVisible = false;
  			}
  		},		
  
  		controlsTimer: null,
  
  		startControlsTimer: function(timeout) {
  
  			var t = this;
  			
  			timeout = typeof timeout != 'undefined' ? timeout : 1500;
  
  			t.killControlsTimer('start');
  
  			t.controlsTimer = setTimeout(function() {
  				//console.log('timer fired');
  				t.hideControls();
  				t.killControlsTimer('hide');
  			}, timeout);
  		},
  
  		killControlsTimer: function(src) {
  
  			var t = this;
  
  			if (t.controlsTimer !== null) {
  				clearTimeout(t.controlsTimer);
  				delete t.controlsTimer;
  				t.controlsTimer = null;
  			}
  		},		
  		
  		controlsEnabled: true,
  		
  		disableControls: function() {
  			var t= this;
  			
  			t.killControlsTimer();
  			t.hideControls(false);
  			this.controlsEnabled = false;
  		},
  		
  		enableControls: function() {
  			var t= this;
  			
  			t.showControls(false);
  			
  			t.controlsEnabled = true;
  		},		
  		
  
  		// Sets up all controls and events
  		meReady: function(media, domNode) {			
  		
  		
  			var t = this,
  				mf = mejs.MediaFeatures,
  				autoplayAttr = domNode.getAttribute('autoplay'),
  				autoplay = !(typeof autoplayAttr == 'undefined' || autoplayAttr === null || autoplayAttr === 'false'),
  				featureIndex,
  				feature;
  
  			// make sure it can't create itself again if a plugin reloads
  			if (t.created)
  				return;
  			else
  				t.created = true;			
  
  			t.media = media;
  			t.domNode = domNode;
  			
  			if (!(mf.isAndroid && t.options.AndroidUseNativeControls) && !(mf.isiPad && t.options.iPadUseNativeControls) && !(mf.isiPhone && t.options.iPhoneUseNativeControls)) {				
  				
  				// two built in features
  				t.buildposter(t, t.controls, t.layers, t.media);
  				t.buildkeyboard(t, t.controls, t.layers, t.media);
  				t.buildoverlays(t, t.controls, t.layers, t.media);
  
  				// grab for use by features
  				t.findTracks();
  
  				// add user-defined features/controls
  				for (featureIndex in t.options.features) {
  					feature = t.options.features[featureIndex];
  					if (t['build' + feature]) {
  						try {
  							t['build' + feature](t, t.controls, t.layers, t.media);
  						} catch (e) {
  							// TODO: report control error
  							//throw e;
  							//console.log('error building ' + feature);
  							//console.log(e);
  						}
  					}
  				}
  
  				t.container.trigger('controlsready');
  				
  				// reset all layers and controls
  				t.setPlayerSize(t.width, t.height);
  				t.setControlsSize();
  				
  
  				// controls fade
  				if (t.isVideo) {
  				
  					if (mejs.MediaFeatures.hasTouch) {
  						
  						// for touch devices (iOS, Android)
  						// show/hide without animation on touch
  						
  						t.$media.bind('touchstart', function() {
  							
  							
  							// toggle controls
  							if (t.controlsAreVisible) {
  								t.hideControls(false);
  							} else {
  								if (t.controlsEnabled) {
  									t.showControls(false);
  								}
  							}
  						});					
  					
  					} else {
  						// click controls
  						var clickElement = (t.media.pluginType == 'native') ? t.$media : $(t.media.pluginElement);
  						
  						// click to play/pause
  						clickElement.click(function() {
  							if (media.paused) {
  								media.play();
  							} else {
  								media.pause();
  							}
  						});
  						
  					
  						// show/hide controls
  						t.container
  							.bind('mouseenter mouseover', function () {
  								if (t.controlsEnabled) {
  									if (!t.options.alwaysShowControls) {								
  										t.killControlsTimer('enter');
  										t.showControls();
  										t.startControlsTimer(2500);		
  									}
  								}
  							})
  							.bind('mousemove', function() {
  								if (t.controlsEnabled) {
  									if (!t.controlsAreVisible) {
  										t.showControls();
  									}
  									//t.killControlsTimer('move');
  									if (!t.options.alwaysShowControls) {
  										t.startControlsTimer(2500);
  									}
  								}
  							})
  							.bind('mouseleave', function () {
  								if (t.controlsEnabled) {
  									if (!t.media.paused && !t.options.alwaysShowControls) {
  										t.startControlsTimer(1000);								
  									}
  								}
  							});
  					}
  					
  					// check for autoplay
  					if (autoplay && !t.options.alwaysShowControls) {
  						t.hideControls();
  					}
  
  					// resizer
  					if (t.options.enableAutosize) {
  						t.media.addEventListener('loadedmetadata', function(e) {
  							// if the <video height> was not set and the options.videoHeight was not set
  							// then resize to the real dimensions
  							if (t.options.videoHeight <= 0 && t.domNode.getAttribute('height') === null && !isNaN(e.target.videoHeight)) {
  								t.setPlayerSize(e.target.videoWidth, e.target.videoHeight);
  								t.setControlsSize();
  								t.media.setVideoSize(e.target.videoWidth, e.target.videoHeight);
  							}
  						}, false);
  					}
  				}
  				
  				// EVENTS
  
  				// FOCUS: when a video starts playing, it takes focus from other players (possibily pausing them)
  				media.addEventListener('play', function() {
  						
  						// go through all other players
  						for (var i=0, il=mejs.players.length; i<il; i++) {
  							var p = mejs.players[i];
  							if (p.id != t.id && t.options.pauseOtherPlayers && !p.paused && !p.ended) {
  								p.pause();
  							}
  							p.hasFocus = false;
  						}
  						
  						t.hasFocus = true;
  				},false);
  								
  
  				// ended for all
  				t.media.addEventListener('ended', function (e) {
  					try{
  						t.media.setCurrentTime(0);
  					} catch (exp) {
  						
  					}
  					t.media.pause();
  					
  					if (t.setProgressRail)
  						t.setProgressRail();
  					if (t.setCurrentRail)
  						t.setCurrentRail();						
  
  					if (t.options.loop) {
  						t.media.play();
  					} else if (!t.options.alwaysShowControls && t.controlsEnabled) {
  						t.showControls();
  					}
  				}, false);
  				
  				// resize on the first play
  				t.media.addEventListener('loadedmetadata', function(e) {
  					if (t.updateDuration) {
  						t.updateDuration();
  					}
  					if (t.updateCurrent) {
  						t.updateCurrent();
  					}
  					
  					if (!t.isFullScreen) {
  						t.setPlayerSize(t.width, t.height);
  						t.setControlsSize();
  					}
  				}, false);
  
  
  				// webkit has trouble doing this without a delay
  				setTimeout(function () {
  					t.setPlayerSize(t.width, t.height);
  					t.setControlsSize();
  				}, 50);
  				
  				// adjust controls whenever window sizes (used to be in fullscreen only)
  				$(window).resize(function() {
  					
  					// don't resize for fullscreen mode				
  					if ( !(t.isFullScreen || (mejs.MediaFeatures.hasTrueNativeFullScreen && document.webkitIsFullScreen)) ) {
  						t.setPlayerSize(t.width, t.height);
  					}
  					
  					// always adjust controls
  					t.setControlsSize();
  				});				
  
  				// TEMP: needs to be moved somewhere else
  				if (t.media.pluginType == 'youtube') {
  					t.container.find('.mejs-overlay-play').hide();	
  				}
  			}
  			
  			// force autoplay for HTML5
  			if (autoplay && media.pluginType == 'native') {
  				media.load();
  				media.play();
  			}
  
  
  			if (t.options.success) {
  				
  				if (typeof t.options.success == 'string') {
  						window[t.options.success](t.media, t.domNode, t);
  				} else {
  						t.options.success(t.media, t.domNode, t);
  				}
  			}
  		},
  
  		handleError: function(e) {
  			var t = this;
  			
  			t.controls.hide();
  		
  			// Tell user that the file cannot be played
  			if (t.options.error) {
  				t.options.error(e);
  			}
  		},
  
  		setPlayerSize: function(width,height) {
  			var t = this;
  
  			if (typeof width != 'undefined')
  				t.width = width;
  				
  			if (typeof height != 'undefined')
  				t.height = height;
  
  			// detect 100% mode
  			if (t.height.toString().indexOf('%') > 0 || t.$node.css('max-width') === '100%') {
  			
  				// do we have the native dimensions yet?
  				var 
  					nativeWidth = (t.media.videoWidth && t.media.videoWidth > 0) ? t.media.videoWidth : t.options.defaultVideoWidth,
  					nativeHeight = (t.media.videoHeight && t.media.videoHeight > 0) ? t.media.videoHeight : t.options.defaultVideoHeight,
  					parentWidth = t.container.parent().width(),
  					newHeight = parseInt(parentWidth * nativeHeight/nativeWidth, 10);
  					
  				if (t.container.parent()[0].tagName.toLowerCase() === 'body') { // && t.container.siblings().count == 0) {
  					parentWidth = $(window).width();
  					newHeight = $(window).height();
  				}
  				
  				if ( newHeight != 0 ) {
  					// set outer container size
  					t.container
  						.width(parentWidth)
  						.height(newHeight);
  						
  					// set native <video>
  					t.$media
  						.width('100%')
  						.height('100%');
  						
  					// set shims
  					t.container.find('object, embed, iframe')
  						.width('100%')
  						.height('100%');
  						
  					// if shim is ready, send the size to the embeded plugin	
  					if (t.isVideo) {
  						if (t.media.setVideoSize) {
  							t.media.setVideoSize(parentWidth, newHeight);
  						}
  					}
  					
  					// set the layers
  					t.layers.children('.mejs-layer')
  						.width('100%')
  						.height('100%');
  				}
  			
  			
  			} else {
  
  				t.container
  					.width(t.width)
  					.height(t.height);
  	
  				t.layers.children('.mejs-layer')
  					.width(t.width)
  					.height(t.height);
  					
  			}
  		},
  
  		setControlsSize: function() {
  			var t = this,
  				usedWidth = 0,
  				railWidth = 0,
  				rail = t.controls.find('.mejs-time-rail'),
  				total = t.controls.find('.mejs-time-total'),
  				current = t.controls.find('.mejs-time-current'),
  				loaded = t.controls.find('.mejs-time-loaded'),
  				others = rail.siblings();
  			
  
  			// allow the size to come from custom CSS
  			if (t.options && !t.options.autosizeProgress) {
  				// Also, frontends devs can be more flexible 
  				// due the opportunity of absolute positioning.
  				railWidth = parseInt(rail.css('width'));
  			}
  			
  			// attempt to autosize
  			if (railWidth === 0 || !railWidth) {
  				
  				// find the size of all the other controls besides the rail
  				others.each(function() {
  					if ($(this).css('position') != 'absolute') {
  						usedWidth += $(this).outerWidth(true);
  					}
  				});
  				
  				// fit the rail into the remaining space
  				railWidth = t.controls.width() - usedWidth - (rail.outerWidth(true) - rail.width());
  			}
  
  			// outer area
  			rail.width(railWidth);
  			// dark space
  			total.width(railWidth - (total.outerWidth(true) - total.width()));
  			
  			if (t.setProgressRail)
  				t.setProgressRail();
  			if (t.setCurrentRail)
  				t.setCurrentRail();				
  		},
  
  
  		buildposter: function(player, controls, layers, media) {
  			var t = this,
  				poster = 
  				$('<div class="mejs-poster mejs-layer">' +
  				'</div>')
  					.appendTo(layers),
  				posterUrl = player.$media.attr('poster');
  
  			// prioriy goes to option (this is useful if you need to support iOS 3.x (iOS completely fails with poster)
  			if (player.options.poster !== '') {
  				posterUrl = player.options.poster;
  			}	
  				
  			// second, try the real poster
  			if (posterUrl !== '' && posterUrl != null) {
  				t.setPoster(posterUrl);
  			} else {
  				poster.hide();
  			}
  
  			media.addEventListener('play',function() {
  				poster.hide();
  			}, false);
  		},
  		
  		setPoster: function(url) {
  			var t = this,
  				posterDiv = t.container.find('.mejs-poster'),
  				posterImg = posterDiv.find('img');
  				
  			if (posterImg.length == 0) {
  				posterImg = $('<img width="100%" height="100%" />').appendTo(posterDiv);
  			}	
  			
  			posterImg.attr('src', url);
  		},
  
  		buildoverlays: function(player, controls, layers, media) {
  			if (!player.isVideo)
  				return;
  
  			var 
  			loading = 
  				$('<div class="mejs-overlay mejs-layer">'+
  					'<div class="mejs-overlay-loading"><span></span></div>'+
  				'</div>')
  				.hide() // start out hidden
  				.appendTo(layers),
  			error = 
  				$('<div class="mejs-overlay mejs-layer">'+
  					'<div class="mejs-overlay-error"></div>'+
  				'</div>')
  				.hide() // start out hidden
  				.appendTo(layers),
  			// this needs to come last so it's on top
  			bigPlay = 
  				$('<div class="mejs-overlay mejs-layer mejs-overlay-play">'+
  					'<div class="mejs-overlay-button"></div>'+
  				'</div>')
  				.appendTo(layers)
  				.click(function() {
  					if (media.paused) {
  						media.play();
  					} else {
  						media.pause();
  					}
  				});
  			
  			/*
  			if (mejs.MediaFeatures.isiOS || mejs.MediaFeatures.isAndroid) {
  				bigPlay.remove();
  				loading.remove();
  			}
  			*/
  	
  
  			// show/hide big play button
  			media.addEventListener('play',function() {
  				bigPlay.hide();
  				loading.hide();
  				controls.find('.mejs-time-buffering').hide();
  				error.hide();
  			}, false);	
  			
  			media.addEventListener('playing', function() {
  				bigPlay.hide();
  				loading.hide();
  				controls.find('.mejs-time-buffering').hide();
  				error.hide();			
  			}, false);
  
  			media.addEventListener('seeking', function() {
  				loading.show();
  				controls.find('.mejs-time-buffering').show();
  			}, false);
  
  			media.addEventListener('seeked', function() {
  				loading.hide();
  				controls.find('.mejs-time-buffering').hide();
  			}, false);
  	
  			media.addEventListener('pause',function() {
  				if (!mejs.MediaFeatures.isiPhone) {
  					bigPlay.show();
  				}
  			}, false);
  			
  			media.addEventListener('waiting', function() {
  				loading.show();	
  				controls.find('.mejs-time-buffering').show();
  			}, false);			
  			
  			
  			// show/hide loading			
  			media.addEventListener('loadeddata',function() {
  				// for some reason Chrome is firing this event
  				//if (mejs.MediaFeatures.isChrome && media.getAttribute && media.getAttribute('preload') === 'none')
  				//	return;
  					
  				loading.show();
  				controls.find('.mejs-time-buffering').show();
  			}, false);	
  			media.addEventListener('canplay',function() {
  				loading.hide();
  				controls.find('.mejs-time-buffering').hide();
  			}, false);	
  
  			// error handling
  			media.addEventListener('error',function() {
  				loading.hide();
  				controls.find('.mejs-time-buffering').hide();
  				error.show();
  				error.find('mejs-overlay-error').html("Error loading this resource");
  			}, false);				
  		},
  		
  		buildkeyboard: function(player, controls, layers, media) {
  
  				var t = this;
  				
  				// listen for key presses
  				$(document).keydown(function(e) {
  						
  						if (player.hasFocus && player.options.enableKeyboard) {
  										
  								// find a matching key
  								for (var i=0, il=player.options.keyActions.length; i<il; i++) {
  										var keyAction = player.options.keyActions[i];
  										
  										for (var j=0, jl=keyAction.keys.length; j<jl; j++) {
  												if (e.keyCode == keyAction.keys[j]) {
  														e.preventDefault();
  														keyAction.action(player, media, e.keyCode);
  														return false;
  												}												
  										}
  								}
  						}
  						
  						return true;
  				});
  				
  				// check if someone clicked outside a player region, then kill its focus
  				$(document).click(function(event) {
  						if ($(event.target).closest('.mejs-container').length == 0) {
  								player.hasFocus = false;
  						}
  				});
  			
  		},
  
  		findTracks: function() {
  			var t = this,
  				tracktags = t.$media.find('track');
  
  			// store for use by plugins
  			t.tracks = [];
  			tracktags.each(function(index, track) {
  				
  				track = $(track);
  				
  				t.tracks.push({
  					srclang: track.attr('srclang').toLowerCase(),
  					src: track.attr('src'),
  					kind: track.attr('kind'),
  					label: track.attr('label') || '',
  					entries: [],
  					isLoaded: false
  				});
  			});
  		},
  		changeSkin: function(className) {
  			this.container[0].className = 'mejs-container ' + className;
  			this.setPlayerSize(this.width, this.height);
  			this.setControlsSize();
  		},
  		play: function() {
  			this.media.play();
  		},
  		pause: function() {
  			this.media.pause();
  		},
  		load: function() {
  			this.media.load();
  		},
  		setMuted: function(muted) {
  			this.media.setMuted(muted);
  		},
  		setCurrentTime: function(time) {
  			this.media.setCurrentTime(time);
  		},
  		getCurrentTime: function() {
  			return this.media.currentTime;
  		},
  		setVolume: function(volume) {
  			this.media.setVolume(volume);
  		},
  		getVolume: function() {
  			return this.media.volume;
  		},
  		setSrc: function(src) {
  			this.media.setSrc(src);
  		},
  		remove: function() {
  			var t = this;
  			
  			if (t.media.pluginType === 'flash') {
  				t.media.remove();
  			} else if (t.media.pluginType === 'native') {
  				t.$media.prop('controls', true);
  			}
  			
  			// grab video and put it back in place
  			if (!t.isDynamic) {
  				t.$node.insertBefore(t.container)
  			}
  			
  			t.container.remove();
  		}
  	};
  
  	// turn into jQuery plugin
  	if (typeof jQuery != 'undefined') {
  		jQuery.fn.mediaelementplayer = function (options) {
  			return this.each(function () {
  				new mejs.MediaElementPlayer(this, options);
  			});
  		};
  	}
  	
  	$(document).ready(function() {
  		// auto enable using JSON attribute
  		$('.mejs-player').mediaelementplayer();
  	});
  	
  	// push out to window
  	window.MediaElementPlayer = mejs.MediaElementPlayer;
  
  })(mejs.$);
  
  (function($) {
  
  	$.extend(mejs.MepDefaults, {
  		playpauseText: 'Play/Pause'
  	});
  
  	// PLAY/pause BUTTON
  	$.extend(MediaElementPlayer.prototype, {
  		buildplaypause: function(player, controls, layers, media) {
  			var 
  				t = this,
  				play = 
  				$('<div class="mejs-button mejs-playpause-button mejs-play" >' +
  					'<button type="button" aria-controls="' + t.id + '" title="' + t.options.playpauseText + '"></button>' +
  				'</div>')
  				.appendTo(controls)
  				.click(function(e) {
  					e.preventDefault();
  				
  					if (media.paused) {
  						media.play();
  					} else {
  						media.pause();
  					}
  					
  					return false;
  				});
  
  			media.addEventListener('play',function() {
  				play.removeClass('mejs-play').addClass('mejs-pause');
  			}, false);
  			media.addEventListener('playing',function() {
  				play.removeClass('mejs-play').addClass('mejs-pause');
  			}, false);
  
  
  			media.addEventListener('pause',function() {
  				play.removeClass('mejs-pause').addClass('mejs-play');
  			}, false);
  			media.addEventListener('paused',function() {
  				play.removeClass('mejs-pause').addClass('mejs-play');
  			}, false);
  		}
  	});
  	
  })(mejs.$);
  (function($) {
  
  	$.extend(mejs.MepDefaults, {
  		stopText: 'Stop'
  	});
  
  	// STOP BUTTON
  	$.extend(MediaElementPlayer.prototype, {
  		buildstop: function(player, controls, layers, media) {
  			var t = this,
  				stop = 
  				$('<div class="mejs-button mejs-stop-button mejs-stop">' +
  					'<button type="button" aria-controls="' + t.id + '" title="' + t.options.stopText + '"></button>' +
  				'</div>')
  				.appendTo(controls)
  				.click(function() {
  					if (!media.paused) {
  						media.pause();
  					}
  					if (media.currentTime > 0) {
  						media.setCurrentTime(0);	
  						controls.find('.mejs-time-current').width('0px');
  						controls.find('.mejs-time-handle').css('left', '0px');
  						controls.find('.mejs-time-float-current').html( mejs.Utility.secondsToTimeCode(0) );
  						controls.find('.mejs-currenttime').html( mejs.Utility.secondsToTimeCode(0) );					
  						layers.find('.mejs-poster').show();
  					}
  				});
  		}
  	});
  	
  })(mejs.$);
  (function($) {
  	// progress/loaded bar
  	$.extend(MediaElementPlayer.prototype, {
  		buildprogress: function(player, controls, layers, media) {
  
  			$('<div class="mejs-time-rail">'+
  				'<span class="mejs-time-total">'+
  					'<span class="mejs-time-buffering"></span>'+
  					'<span class="mejs-time-loaded"></span>'+
  					'<span class="mejs-time-current"></span>'+
  					'<span class="mejs-time-handle"></span>'+
  					'<span class="mejs-time-float">' + 
  						'<span class="mejs-time-float-current">00:00</span>' + 
  						'<span class="mejs-time-float-corner"></span>' + 
  					'</span>'+
  				'</span>'+
  			'</div>')
  				.appendTo(controls);
  				controls.find('.mejs-time-buffering').hide();
  
  			var 
  				t = this,
  				total = controls.find('.mejs-time-total'),
  				loaded  = controls.find('.mejs-time-loaded'),
  				current  = controls.find('.mejs-time-current'),
  				handle  = controls.find('.mejs-time-handle'),
  				timefloat  = controls.find('.mejs-time-float'),
  				timefloatcurrent  = controls.find('.mejs-time-float-current'),
  				handleMouseMove = function (e) {
  					// mouse position relative to the object
  					var x = e.pageX,
  						offset = total.offset(),
  						width = total.outerWidth(),
  						percentage = 0,
  						newTime = 0,
  						pos = x - offset.left;
  
  
  					if (x > offset.left && x <= width + offset.left && media.duration) {
  						percentage = ((x - offset.left) / width);
  						newTime = (percentage <= 0.02) ? 0 : percentage * media.duration;
  
  						// seek to where the mouse is
  						if (mouseIsDown) {
  							media.setCurrentTime(newTime);
  						}
  
  						// position floating time box
  						if (!mejs.MediaFeatures.hasTouch) {
  								timefloat.css('left', pos);
  								timefloatcurrent.html( mejs.Utility.secondsToTimeCode(newTime) );
  								timefloat.show();
  						}
  					}
  				},
  				mouseIsDown = false,
  				mouseIsOver = false;
  
  			// handle clicks
  			//controls.find('.mejs-time-rail').delegate('span', 'click', handleMouseMove);
  			total
  				.bind('mousedown', function (e) {
  					// only handle left clicks
  					if (e.which === 1) {
  						mouseIsDown = true;
  						handleMouseMove(e);
  						$(document)
  							.bind('mousemove.dur', function(e) {
  								handleMouseMove(e);
  							})
  							.bind('mouseup.dur', function (e) {
  								mouseIsDown = false;
  								timefloat.hide();
  								$(document).unbind('.dur');
  							});
  						return false;
  					}
  				})
  				.bind('mouseenter', function(e) {
  					mouseIsOver = true;
  					$(document).bind('mousemove.dur', function(e) {
  						handleMouseMove(e);
  					});
  					if (!mejs.MediaFeatures.hasTouch) {
  						timefloat.show();
  					}
  				})
  				.bind('mouseleave',function(e) {
  					mouseIsOver = false;
  					if (!mouseIsDown) {
  						$(document).unbind('.dur');
  						timefloat.hide();
  					}
  				});
  
  			// loading
  			media.addEventListener('progress', function (e) {
  				player.setProgressRail(e);
  				player.setCurrentRail(e);
  			}, false);
  
  			// current time
  			media.addEventListener('timeupdate', function(e) {
  				player.setProgressRail(e);
  				player.setCurrentRail(e);
  			}, false);
  			
  			
  			// store for later use
  			t.loaded = loaded;
  			t.total = total;
  			t.current = current;
  			t.handle = handle;
  		},
  		setProgressRail: function(e) {
  
  			var
  				t = this,
  				target = (e != undefined) ? e.target : t.media,
  				percent = null;			
  
  			// newest HTML5 spec has buffered array (FF4, Webkit)
  			if (target && target.buffered && target.buffered.length > 0 && target.buffered.end && target.duration) {
  				// TODO: account for a real array with multiple values (only Firefox 4 has this so far) 
  				percent = target.buffered.end(0) / target.duration;
  			} 
  			// Some browsers (e.g., FF3.6 and Safari 5) cannot calculate target.bufferered.end()
  			// to be anything other than 0. If the byte count is available we use this instead.
  			// Browsers that support the else if do not seem to have the bufferedBytes value and
  			// should skip to there. Tested in Safari 5, Webkit head, FF3.6, Chrome 6, IE 7/8.
  			else if (target && target.bytesTotal != undefined && target.bytesTotal > 0 && target.bufferedBytes != undefined) {
  				percent = target.bufferedBytes / target.bytesTotal;
  			}
  			// Firefox 3 with an Ogg file seems to go this way
  			else if (e && e.lengthComputable && e.total != 0) {
  				percent = e.loaded/e.total;
  			}
  
  			// finally update the progress bar
  			if (percent !== null) {
  				percent = Math.min(1, Math.max(0, percent));
  				// update loaded bar
  				if (t.loaded && t.total) {
  					t.loaded.width(t.total.width() * percent);
  				}
  			}
  		},
  		setCurrentRail: function() {
  
  			var t = this;
  		
  			if (t.media.currentTime != undefined && t.media.duration) {
  
  				// update bar and handle
  				if (t.total && t.handle) {
  					var 
  						newWidth = t.total.width() * t.media.currentTime / t.media.duration,
  						handlePos = newWidth - (t.handle.outerWidth(true) / 2);
  
  					t.current.width(newWidth);
  					t.handle.css('left', handlePos);
  				}
  			}
  
  		}	
  	});
  })(mejs.$);
  (function($) {
  	
  	// options
  	$.extend(mejs.MepDefaults, {
  		duration: -1,
  		timeAndDurationSeparator: ' <span> | </span> '
  	});
  
  
  	// current and duration 00:00 / 00:00
  	$.extend(MediaElementPlayer.prototype, {
  		buildcurrent: function(player, controls, layers, media) {
  			var t = this;
  			
  			$('<div class="mejs-time">'+
  					'<span class="mejs-currenttime">' + (player.options.alwaysShowHours ? '00:' : '')
  					+ (player.options.showTimecodeFrameCount? '00:00:00':'00:00')+ '</span>'+
  					'</div>')
  					.appendTo(controls);
  			
  			t.currenttime = t.controls.find('.mejs-currenttime');
  
  			media.addEventListener('timeupdate',function() {
  				player.updateCurrent();
  			}, false);
  		},
  
  
  		buildduration: function(player, controls, layers, media) {
  			var t = this;
  			
  			if (controls.children().last().find('.mejs-currenttime').length > 0) {
  				$(t.options.timeAndDurationSeparator +
  					'<span class="mejs-duration">' + 
  						(t.options.duration > 0 ? 
  							mejs.Utility.secondsToTimeCode(t.options.duration, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount,  t.options.framesPerSecond || 25) :
  				   			((player.options.alwaysShowHours ? '00:' : '') + (player.options.showTimecodeFrameCount? '00:00:00':'00:00')) 
  				   		) + 
  					'</span>')
  					.appendTo(controls.find('.mejs-time'));
  			} else {
  
  				// add class to current time
  				controls.find('.mejs-currenttime').parent().addClass('mejs-currenttime-container');
  				
  				$('<div class="mejs-time mejs-duration-container">'+
  					'<span class="mejs-duration">' + 
  						(t.options.duration > 0 ? 
  							mejs.Utility.secondsToTimeCode(t.options.duration, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount,  t.options.framesPerSecond || 25) :
  				   			((player.options.alwaysShowHours ? '00:' : '') + (player.options.showTimecodeFrameCount? '00:00:00':'00:00')) 
  				   		) + 
  					'</span>' +
  				'</div>')
  				.appendTo(controls);
  			}
  			
  			t.durationD = t.controls.find('.mejs-duration');
  
  			media.addEventListener('timeupdate',function() {
  				player.updateDuration();
  			}, false);
  		},
  		
  		updateCurrent:  function() {
  			var t = this;
  
  			if (t.currenttime) {
  				t.currenttime.html(mejs.Utility.secondsToTimeCode(t.media.currentTime, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount,  t.options.framesPerSecond || 25));
  			}
  		},
  		
  		updateDuration: function() {	
  			var t = this;
  			
  			if (t.media.duration && t.durationD) {
  				t.durationD.html(mejs.Utility.secondsToTimeCode(t.media.duration, t.options.alwaysShowHours, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25));
  			}		
  		}
  	});
  
  })(mejs.$);
  (function($) {
  
  	$.extend(mejs.MepDefaults, {
  		muteText: 'Mute Toggle',
  		hideVolumeOnTouchDevices: true,
  		
  		audioVolume: 'horizontal',
  		videoVolume: 'vertical'
  	});
  
  	$.extend(MediaElementPlayer.prototype, {
  		buildvolume: function(player, controls, layers, media) {
  				
  			// Android and iOS don't support volume controls
  			if (mejs.MediaFeatures.hasTouch && this.options.hideVolumeOnTouchDevices)
  				return;
  			
  			var t = this,
  				mode = (t.isVideo) ? t.options.videoVolume : t.options.audioVolume,
  				mute = (mode == 'horizontal') ?
  				
  				// horizontal version
  				$('<div class="mejs-button mejs-volume-button mejs-mute">'+
  					'<button type="button" aria-controls="' + t.id + '" title="' + t.options.muteText + '"></button>'+
  				'</div>' +
  				'<div class="mejs-horizontal-volume-slider">'+ // outer background
  					'<div class="mejs-horizontal-volume-total"></div>'+ // line background
  					'<div class="mejs-horizontal-volume-current"></div>'+ // current volume
  					'<div class="mejs-horizontal-volume-handle"></div>'+ // handle
  				'</div>'
  				)
  					.appendTo(controls) :
  				
  				// vertical version
  				$('<div class="mejs-button mejs-volume-button mejs-mute">'+
  					'<button type="button" aria-controls="' + t.id + '" title="' + t.options.muteText + '"></button>'+
  					'<div class="mejs-volume-slider">'+ // outer background
  						'<div class="mejs-volume-total"></div>'+ // line background
  						'<div class="mejs-volume-current"></div>'+ // current volume
  						'<div class="mejs-volume-handle"></div>'+ // handle
  					'</div>'+
  				'</div>')
  					.appendTo(controls),
  			volumeSlider = t.container.find('.mejs-volume-slider, .mejs-horizontal-volume-slider'),
  			volumeTotal = t.container.find('.mejs-volume-total, .mejs-horizontal-volume-total'),
  			volumeCurrent = t.container.find('.mejs-volume-current, .mejs-horizontal-volume-current'),
  			volumeHandle = t.container.find('.mejs-volume-handle, .mejs-horizontal-volume-handle'),
  
  			positionVolumeHandle = function(volume, secondTry) {
  
  				if (!volumeSlider.is(':visible') && typeof secondTry != 'undefined') {
  					volumeSlider.show();
  					positionVolumeHandle(volume, true);
  					volumeSlider.hide()
  					return;
  				}
  			
  				// correct to 0-1
  				volume = Math.max(0,volume);
  				volume = Math.min(volume,1);					
  				
  				// ajust mute button style
  				if (volume == 0) {
  					mute.removeClass('mejs-mute').addClass('mejs-unmute');
  				} else {
  					mute.removeClass('mejs-unmute').addClass('mejs-mute');
  				}				
  
  				// position slider 
  				if (mode == 'vertical') {
  					var 
  					
  						// height of the full size volume slider background
  						totalHeight = volumeTotal.height(),
  						
  						// top/left of full size volume slider background
  						totalPosition = volumeTotal.position(),
  						
  						// the new top position based on the current volume
  						// 70% volume on 100px height == top:30px
  						newTop = totalHeight - (totalHeight * volume);
  	
  					// handle
  					volumeHandle.css('top', totalPosition.top + newTop - (volumeHandle.height() / 2));
  	
  					// show the current visibility
  					volumeCurrent.height(totalHeight - newTop );
  					volumeCurrent.css('top', totalPosition.top + newTop);
  				} else {
  					var 
  					
  						// height of the full size volume slider background
  						totalWidth = volumeTotal.width(),
  						
  						// top/left of full size volume slider background
  						totalPosition = volumeTotal.position(),
  						
  						// the new left position based on the current volume
  						newLeft = totalWidth * volume;
  	
  					// handle
  					volumeHandle.css('left', totalPosition.left + newLeft - (volumeHandle.width() / 2));
  	
  					// rezize the current part of the volume bar
  					volumeCurrent.width( newLeft );
  				}
  			},
  			handleVolumeMove = function(e) {
  				
  				var volume = null,
  					totalOffset = volumeTotal.offset();
  				
  				// calculate the new volume based on the moust position
  				if (mode == 'vertical') {
  				
  					var
  						railHeight = volumeTotal.height(),
  						totalTop = parseInt(volumeTotal.css('top').replace(/px/,''),10),
  						newY = e.pageY - totalOffset.top;
  						
  					volume = (railHeight - newY) / railHeight;
  						
  					// the controls just hide themselves (usually when mouse moves too far up)
  					if (totalOffset.top == 0 || totalOffset.left == 0)
  						return;
  					
  				} else {
  					var
  						railWidth = volumeTotal.width(),
  						newX = e.pageX - totalOffset.left;
  						
  					volume = newX / railWidth;
  				}
  				
  				// ensure the volume isn't outside 0-1
  				volume = Math.max(0,volume);
  				volume = Math.min(volume,1);
  				
  				// position the slider and handle			
  				positionVolumeHandle(volume);
  				
  				// set the media object (this will trigger the volumechanged event)
  				if (volume == 0) {
  					media.setMuted(true);
  				} else {
  					media.setMuted(false);
  				}
  				media.setVolume(volume);			
  			},
  			mouseIsDown = false,
  			mouseIsOver = false;
  
  			// SLIDER
  			
  			mute
  				.hover(function() {
  					volumeSlider.show();
  					mouseIsOver = true;
  				}, function() {
  					mouseIsOver = false;	
  						
  					if (!mouseIsDown && mode == 'vertical')	{
  						volumeSlider.hide();
  					}
  				});
  			
  			volumeSlider
  				.bind('mouseover', function() {
  					mouseIsOver = true;	
  				})
  				.bind('mousedown', function (e) {
  					handleVolumeMove(e);
  					$(document)
  						.bind('mousemove.vol', function(e) {
  							handleVolumeMove(e);
  						})
  						.bind('mouseup.vol', function () {
  							mouseIsDown = false;
  							$(document).unbind('.vol');
  
  							if (!mouseIsOver && mode == 'vertical') {
  								volumeSlider.hide();
  							}
  						});
  					mouseIsDown = true;
  						
  					return false;
  				});
  
  
  			// MUTE button
  			mute.find('button').click(function() {
  				media.setMuted( !media.muted );
  			});
  
  			// listen for volume change events from other sources
  			media.addEventListener('volumechange', function(e) {
  				if (!mouseIsDown) {
  					if (media.muted) {
  						positionVolumeHandle(0);
  						mute.removeClass('mejs-mute').addClass('mejs-unmute');
  					} else {
  						positionVolumeHandle(media.volume);
  						mute.removeClass('mejs-unmute').addClass('mejs-mute');
  					}
  				}
  			}, false);
  
  			if (t.container.is(':visible')) {
  				// set initial volume
  				positionVolumeHandle(player.options.startVolume);
  				
  				// shim gets the startvolume as a parameter, but we have to set it on the native <video> and <audio> elements
  				if (media.pluginType === 'native') {
  					media.setVolume(player.options.startVolume);
  				}
  			}
  		}
  	});
  	
  })(mejs.$);
  
  (function($) {
  	
  	$.extend(mejs.MepDefaults, {
  		usePluginFullScreen: true,
  		newWindowCallback: function() { return '';},
  		fullscreenText: 'Fullscreen'
  	});
  	
  	$.extend(MediaElementPlayer.prototype, {
  		
  		isFullScreen: false,
  		
  		isNativeFullScreen: false,
  		
  		docStyleOverflow: null,
  		
  		isInIframe: false,
  		
  		buildfullscreen: function(player, controls, layers, media) {
  
  			if (!player.isVideo)
  				return;
  				
  			player.isInIframe = (window.location != window.parent.location);
  				
  			// native events
  			if (mejs.MediaFeatures.hasTrueNativeFullScreen) {
  				
  				// chrome doesn't alays fire this in an iframe
  				var target = null;
  				
  				if (mejs.MediaFeatures.hasMozNativeFullScreen) {
  					target = $(document);
  				} else {
  					target = player.container;
  				}
  				
  				target.bind(mejs.MediaFeatures.fullScreenEventName, function(e) {
  							
  					if (mejs.MediaFeatures.isFullScreen()) {
  						player.isNativeFullScreen = true;
  						// reset the controls once we are fully in full screen
  						player.setControlsSize();
  					} else {
  						player.isNativeFullScreen = false;
  						// when a user presses ESC
  						// make sure to put the player back into place								
  						player.exitFullScreen();				
  					}
  				});
  			}
  
  			var t = this,		
  				normalHeight = 0,
  				normalWidth = 0,
  				container = player.container,						
  				fullscreenBtn = 
  					$('<div class="mejs-button mejs-fullscreen-button">' + 
  						'<button type="button" aria-controls="' + t.id + '" title="' + t.options.fullscreenText + '"></button>' + 
  					'</div>')
  					.appendTo(controls);
  				
  				if (t.media.pluginType === 'native' || (!t.options.usePluginFullScreen && !mejs.MediaFeatures.isFirefox)) {
  					
  					fullscreenBtn.click(function() {
  						var isFullScreen = (mejs.MediaFeatures.hasTrueNativeFullScreen && mejs.MediaFeatures.isFullScreen()) || player.isFullScreen;													
  						
  						if (isFullScreen) {
  							player.exitFullScreen();
  						} else {						
  							player.enterFullScreen();
  						}
  					});
  					
  				} else {
  
  					var hideTimeout = null,
  						supportsPointerEvents = (function() {
  							// TAKEN FROM MODERNIZR
  							var element = document.createElement('x'),
  								documentElement = document.documentElement,
  								getComputedStyle = window.getComputedStyle,
  								supports;
  							if(!('pointerEvents' in element.style)){
  								return false;
  							}
  							element.style.pointerEvents = 'auto';
  							element.style.pointerEvents = 'x';
  							documentElement.appendChild(element);
  							supports = getComputedStyle && 
  								getComputedStyle(element, '').pointerEvents === 'auto';
  							documentElement.removeChild(element);
  							return !!supports;							
  						})();
  						
  					//console.log('supportsPointerEvents', supportsPointerEvents);
  						
  					if (supportsPointerEvents && !mejs.MediaFeatures.isOpera) { // opera doesn't allow this :(
  						
  						// allows clicking through the fullscreen button and controls down directly to Flash
  						
  						/*
  						 When a user puts his mouse over the fullscreen button, the controls are disabled
  						 So we put a div over the video and another one on iether side of the fullscreen button
  						 that caputre mouse movement
  						 and restore the controls once the mouse moves outside of the fullscreen button
  						*/
  						
  						var fullscreenIsDisabled = false,
  							restoreControls = function() {
  								if (fullscreenIsDisabled) {
  									// hide the hovers
  									videoHoverDiv.hide();
  									controlsLeftHoverDiv.hide();
  									controlsRightHoverDiv.hide();
  									
  									// restore the control bar
  									fullscreenBtn.css('pointer-events', '');
  									t.controls.css('pointer-events', '');
  									
  									// store for later
  									fullscreenIsDisabled = false;
  								}
  							},
  							videoHoverDiv = $('<div class="mejs-fullscreen-hover" />').appendTo(t.container).mouseover(restoreControls),
  							controlsLeftHoverDiv = $('<div class="mejs-fullscreen-hover"  />').appendTo(t.container).mouseover(restoreControls),
  							controlsRightHoverDiv = $('<div class="mejs-fullscreen-hover"  />').appendTo(t.container).mouseover(restoreControls),
  							positionHoverDivs = function() {
  								var style = {position: 'absolute', top: 0, left: 0}; //, backgroundColor: '#f00'};
  								videoHoverDiv.css(style);
  								controlsLeftHoverDiv.css(style);
  								controlsRightHoverDiv.css(style);
  								
  								// over video, but not controls
  								videoHoverDiv
  									.width( t.container.width() )
  									.height( t.container.height() - t.controls.height() );
  								
  								// over controls, but not the fullscreen button
  								var fullScreenBtnOffset = fullscreenBtn.offset().left - t.container.offset().left;
  									fullScreenBtnWidth = fullscreenBtn.outerWidth(true);
  									
  								controlsLeftHoverDiv
  									.width( fullScreenBtnOffset )
  									.height( t.controls.height() )
  									.css({top: t.container.height() - t.controls.height()});
  									
  								// after the fullscreen button
  								controlsRightHoverDiv
  									.width( t.container.width() - fullScreenBtnOffset - fullScreenBtnWidth )
  									.height( t.controls.height() )
  									.css({top: t.container.height() - t.controls.height(),
  										 left: fullScreenBtnOffset + fullScreenBtnWidth});								
  							};
  						
  						$(document).resize(function() {
  							positionHoverDivs();
  						});
  												
  						// on hover, kill the fullscreen button's HTML handling, allowing clicks down to Flash
  						fullscreenBtn
  							.mouseover(function() {
  								
  								if (!t.isFullScreen) {
  									
  									var buttonPos = fullscreenBtn.offset(),
  										containerPos = player.container.offset();
  									
  									// move the button in Flash into place
  									media.positionFullscreenButton(buttonPos.left - containerPos.left, buttonPos.top - containerPos.top, false);									
  									
  									// allows click through
  									fullscreenBtn.css('pointer-events', 'none');
  									t.controls.css('pointer-events', 'none');
  									
  									// show the divs that will restore things
  									videoHoverDiv.show();
  									controlsRightHoverDiv.show();
  									controlsLeftHoverDiv.show();
  									positionHoverDivs();
  									
  									fullscreenIsDisabled = true;
  								}
  							
  							});
  						
  						// restore controls anytime the user enters or leaves fullscreen	
  						media.addEventListener('fullscreenchange', function(e) {
  							restoreControls();
  						});
  						
  						
  						// the mouseout event doesn't work on the fullscren button, because we already killed the pointer-events
  						// so we use the document.mousemove event to restore controls when the mouse moves outside the fullscreen button 
  						/*
  						$(document).mousemove(function(e) {
  							
  							// if the mouse is anywhere but the fullsceen button, then restore it all
  							if (fullscreenIsDisabled) {
  								
  								var fullscreenBtnPos = fullscreenBtn.offset();
  								
  
  								if (e.pageY < fullscreenBtnPos.top || e.pageY > fullscreenBtnPos.top + fullscreenBtn.outerHeight(true) ||
  									e.pageX < fullscreenBtnPos.left || e.pageX > fullscreenBtnPos.left + fullscreenBtn.outerWidth(true)
  									) {
  								
  									fullscreenBtn.css('pointer-events', '');
  									t.controls.css('pointer-events', '');
  									
  									fullscreenIsDisabled = false;
  								}
  							}
  						});
  						*/
  						
  						
  					} else {
  						
  						// the hover state will show the fullscreen button in Flash to hover up and click
  						
  						fullscreenBtn
  							.mouseover(function() {
  								
  								if (hideTimeout !== null) {
  									clearTimeout(hideTimeout);
  									delete hideTimeout;
  								}
  								
  								var buttonPos = fullscreenBtn.offset(),
  									containerPos = player.container.offset();
  									
  								media.positionFullscreenButton(buttonPos.left - containerPos.left, buttonPos.top - containerPos.top, true);
  							
  							})
  							.mouseout(function() {
  							
  								if (hideTimeout !== null) {
  									clearTimeout(hideTimeout);
  									delete hideTimeout;
  								}
  								
  								hideTimeout = setTimeout(function() {	
  									media.hideFullscreenButton();
  								}, 1500);
  								
  								
  							});						
  					}
  				}
  			
  			player.fullscreenBtn = fullscreenBtn;	
  
  			$(document).bind('keydown',function (e) {
  				if (((mejs.MediaFeatures.hasTrueNativeFullScreen && mejs.MediaFeatures.isFullScreen()) || t.isFullScreen) && e.keyCode == 27) {
  					player.exitFullScreen();
  				}
  			});
  				
  		},
  		enterFullScreen: function() {
  			
  			var t = this;
  			
  			// firefox+flash can't adjust plugin sizes without resetting :(
  			if (t.media.pluginType !== 'native' && (mejs.MediaFeatures.isFirefox || t.options.usePluginFullScreen)) {
  				//t.media.setFullscreen(true);
  				//player.isFullScreen = true;
  				return;
  			}			
  						
  			// store overflow 
  			docStyleOverflow = document.documentElement.style.overflow;
  			// set it to not show scroll bars so 100% will work
  			document.documentElement.style.overflow = 'hidden';			
  		
  			// store sizing
  			normalHeight = t.container.height();
  			normalWidth = t.container.width();
  			
  			// attempt to do true fullscreen (Safari 5.1 and Firefox Nightly only for now)
  			if (t.media.pluginType === 'native') {
  				if (mejs.MediaFeatures.hasTrueNativeFullScreen) {
  							
  					mejs.MediaFeatures.requestFullScreen(t.container[0]);
  					//return;
  					
  					if (t.isInIframe) {
  						// sometimes exiting from fullscreen doesn't work
  						// notably in Chrome <iframe>. Fixed in version 17
  						setTimeout(function checkFullscreen() {
  								
  							if (t.isNativeFullScreen) {
  								
  								// check if the video is suddenly not really fullscreen
  								if ($(window).width() !== screen.width) {
  									// manually exit
  									t.exitFullScreen();
  								} else {
  									// test again
  									setTimeout(checkFullscreen, 500);														
  								}
  							}
  							
  							
  						}, 500);
  					}
  					
  				} else if (mejs.MediaFeatures.hasSemiNativeFullScreen) {
  					t.media.webkitEnterFullscreen();
  					return;
  				}
  			}
  			
  			// check for iframe launch
  			if (t.isInIframe) {
  				var url = t.options.newWindowCallback(this);
  				
  				
  				if (url !== '') {
  					
  					// launch immediately
  					if (!mejs.MediaFeatures.hasTrueNativeFullScreen) {
  						t.pause();
  						window.open(url, t.id, 'top=0,left=0,width=' + screen.availWidth + ',height=' + screen.availHeight + ',resizable=yes,scrollbars=no,status=no,toolbar=no');
  						return;
  					} else {
  						setTimeout(function() {
  							if (!t.isNativeFullScreen) {
  								t.pause();
  								window.open(url, t.id, 'top=0,left=0,width=' + screen.availWidth + ',height=' + screen.availHeight + ',resizable=yes,scrollbars=no,status=no,toolbar=no');								
  							}
  						}, 250);
  					}
  				}	
  				
  			}
  			
  			// full window code
  
  			
  
  			// make full size
  			t.container
  				.addClass('mejs-container-fullscreen')
  				.width('100%')
  				.height('100%');
  				//.css({position: 'fixed', left: 0, top: 0, right: 0, bottom: 0, overflow: 'hidden', width: '100%', height: '100%', 'z-index': 1000});				
  
  			// Only needed for safari 5.1 native full screen, can cause display issues elsewhere
  			// Actually, it seems to be needed for IE8, too
  			//if (mejs.MediaFeatures.hasTrueNativeFullScreen) {
  				setTimeout(function() {
  					t.container.css({width: '100%', height: '100%'});
  					t.setControlsSize();
  				}, 500);
  			//}
  				
  			if (t.pluginType === 'native') {
  				t.$media
  					.width('100%')
  					.height('100%');
  			} else {
  				t.container.find('object, embed, iframe')
  					.width('100%')
  					.height('100%');
  					
  				//if (!mejs.MediaFeatures.hasTrueNativeFullScreen) {
  					t.media.setVideoSize($(window).width(),$(window).height());
  				//}
  			}
  			
  			t.layers.children('div')
  				.width('100%')
  				.height('100%');
  
  			if (t.fullscreenBtn) {
  				t.fullscreenBtn
  					.removeClass('mejs-fullscreen')
  					.addClass('mejs-unfullscreen');
  			}
  
  			t.setControlsSize();
  			t.isFullScreen = true;
  		},
  		
  		exitFullScreen: function() {
  			
  			var t = this;		
  		
  			// firefox can't adjust plugins
  			if (t.media.pluginType !== 'native' && mejs.MediaFeatures.isFirefox) {				
  				t.media.setFullscreen(false);
  				//player.isFullScreen = false;
  				return;
  			}		
  		
  			// come outo of native fullscreen
  			if (mejs.MediaFeatures.hasTrueNativeFullScreen && (mejs.MediaFeatures.isFullScreen() || t.isFullScreen)) {
  				mejs.MediaFeatures.cancelFullScreen();
  			}	
  
  			// restore scroll bars to document
  			document.documentElement.style.overflow = docStyleOverflow;					
  				
  			t.container
  				.removeClass('mejs-container-fullscreen')
  				.width(normalWidth)
  				.height(normalHeight);
  				//.css({position: '', left: '', top: '', right: '', bottom: '', overflow: 'inherit', width: normalWidth + 'px', height: normalHeight + 'px', 'z-index': 1});
  			
  			if (t.pluginType === 'native') {
  				t.$media
  					.width(normalWidth)
  					.height(normalHeight);
  			} else {
  				t.container.find('object embed')
  					.width(normalWidth)
  					.height(normalHeight);
  					
  				t.media.setVideoSize(normalWidth, normalHeight);
  			}				
  
  			t.layers.children('div')
  				.width(normalWidth)
  				.height(normalHeight);
  
  			t.fullscreenBtn
  				.removeClass('mejs-unfullscreen')
  				.addClass('mejs-fullscreen');
  
  			t.setControlsSize();
  			t.isFullScreen = false;
  		}	
  	});
  
  })(mejs.$);
  
  (function($) {
  
  	// add extra default options 
  	$.extend(mejs.MepDefaults, {
  		// this will automatically turn on a <track>
  		startLanguage: '',
  		
  		tracksText: 'Captions/Subtitles'
  	});
  
  	$.extend(MediaElementPlayer.prototype, {
  	
  		hasChapters: false,
  
  		buildtracks: function(player, controls, layers, media) {
  			if (!player.isVideo)
  				return;
  
  			if (player.tracks.length == 0)
  				return;
  
  			var t= this, i, options = '';
  
  			player.chapters = 
  					$('<div class="mejs-chapters mejs-layer"></div>')
  						.prependTo(layers).hide();
  			player.captions = 
  					$('<div class="mejs-captions-layer mejs-layer"><div class="mejs-captions-position"><span class="mejs-captions-text"></span></div></div>')
  						.prependTo(layers).hide();
  			player.captionsText = player.captions.find('.mejs-captions-text');
  			player.captionsButton = 
  					$('<div class="mejs-button mejs-captions-button">'+
  						'<button type="button" aria-controls="' + t.id + '" title="' + t.options.tracksText + '"></button>'+
  						'<div class="mejs-captions-selector">'+
  							'<ul>'+
  								'<li>'+
  									'<input type="radio" name="' + player.id + '_captions" id="' + player.id + '_captions_none" value="none" checked="checked" />' +
  									'<label for="' + player.id + '_captions_none">None</label>'+
  								'</li>'	+
  							'</ul>'+
  						'</div>'+
  					'</div>')
  						.appendTo(controls)
  						
  						// hover
  						.hover(function() {
  							$(this).find('.mejs-captions-selector').css('visibility','visible');
  						}, function() {
  							$(this).find('.mejs-captions-selector').css('visibility','hidden');
  						})					
  						
  						// handle clicks to the language radio buttons
  						.delegate('input[type=radio]','click',function() {
  							lang = this.value;
  
  							if (lang == 'none') {
  								player.selectedTrack = null;
  							} else {
  								for (i=0; i<player.tracks.length; i++) {
  									if (player.tracks[i].srclang == lang) {
  										player.selectedTrack = player.tracks[i];
  										player.captions.attr('lang', player.selectedTrack.srclang);
  										player.displayCaptions();
  										break;
  									}
  								}
  							}
  						});
  						//.bind('mouseenter', function() {
  						//	player.captionsButton.find('.mejs-captions-selector').css('visibility','visible')
  						//});
  
  			if (!player.options.alwaysShowControls) {
  				// move with controls
  				player.container
  					.bind('mouseenter', function () {
  						// push captions above controls
  						player.container.find('.mejs-captions-position').addClass('mejs-captions-position-hover');
  
  					})
  					.bind('mouseleave', function () {
  						if (!media.paused) {
  							// move back to normal place
  							player.container.find('.mejs-captions-position').removeClass('mejs-captions-position-hover');
  						}
  					});
  			} else {
  				player.container.find('.mejs-captions-position').addClass('mejs-captions-position-hover');
  			}
  
  			player.trackToLoad = -1;
  			player.selectedTrack = null;
  			player.isLoadingTrack = false;
  
  			
  
  			// add to list
  			for (i=0; i<player.tracks.length; i++) {
  				if (player.tracks[i].kind == 'subtitles') {
  					player.addTrackButton(player.tracks[i].srclang, player.tracks[i].label);
  				}
  			}
  
  			player.loadNextTrack();
  
  
  			media.addEventListener('timeupdate',function(e) {
  				player.displayCaptions();
  			}, false);
  
  			media.addEventListener('loadedmetadata', function(e) {
  				player.displayChapters();
  			}, false);
  
  			player.container.hover(
  				function () {
  					// chapters
  					if (player.hasChapters) {
  						player.chapters.css('visibility','visible');
  						player.chapters.fadeIn(200).height(player.chapters.find('.mejs-chapter').outerHeight());
  					}
  				},
  				function () {
  					if (player.hasChapters && !media.paused) {
  						player.chapters.fadeOut(200, function() {
  							$(this).css('visibility','hidden');
  							$(this).css('display','block');
  						});
  					}
  				});
  				
  			// check for autoplay
  			if (player.node.getAttribute('autoplay') !== null) {
  				player.chapters.css('visibility','hidden');
  			}
  		},
  
  		loadNextTrack: function() {
  			var t = this;
  
  			t.trackToLoad++;
  			if (t.trackToLoad < t.tracks.length) {
  				t.isLoadingTrack = true;
  				t.loadTrack(t.trackToLoad);
  			} else {
  				// add done?
  				t.isLoadingTrack = false;
  			}
  		},
  
  		loadTrack: function(index){
  			var
  				t = this,
  				track = t.tracks[index],
  				after = function() {
  
  					track.isLoaded = true;
  
  					// create button
  					//t.addTrackButton(track.srclang);
  					t.enableTrackButton(track.srclang, track.label);
  
  					t.loadNextTrack();
  
  				};
  
  
  			$.ajax({
  				url: track.src,
  				dataType: "text",
  				success: function(d) {
  
  					// parse the loaded file
  					if (typeof d == "string" && (/<tt\s+xml/ig).exec(d)) {
  						track.entries = mejs.TrackFormatParser.dfxp.parse(d);					
  					} else {	
  						track.entries = mejs.TrackFormatParser.webvvt.parse(d);
  					}
  					
  					after();
  
  					if (track.kind == 'chapters' && t.media.duration > 0) {
  						t.drawChapters(track);
  					}
  				},
  				error: function() {
  					t.loadNextTrack();
  				}
  			});
  		},
  
  		enableTrackButton: function(lang, label) {
  			var t = this;
  			
  			if (label === '') {
  				label = mejs.language.codes[lang] || lang;
  			}			
  
  			t.captionsButton
  				.find('input[value=' + lang + ']')
  					.prop('disabled',false)
  				.siblings('label')
  					.html( label );
  
  			// auto select
  			if (t.options.startLanguage == lang) {
  				$('#' + t.id + '_captions_' + lang).click();
  			}
  
  			t.adjustLanguageBox();
  		},
  
  		addTrackButton: function(lang, label) {
  			var t = this;
  			if (label === '') {
  				label = mejs.language.codes[lang] || lang;
  			}
  
  			t.captionsButton.find('ul').append(
  				$('<li>'+
  					'<input type="radio" name="' + t.id + '_captions" id="' + t.id + '_captions_' + lang + '" value="' + lang + '" disabled="disabled" />' +
  					'<label for="' + t.id + '_captions_' + lang + '">' + label + ' (loading)' + '</label>'+
  				'</li>')
  			);
  
  			t.adjustLanguageBox();
  
  			// remove this from the dropdownlist (if it exists)
  			t.container.find('.mejs-captions-translations option[value=' + lang + ']').remove();
  		},
  
  		adjustLanguageBox:function() {
  			var t = this;
  			// adjust the size of the outer box
  			t.captionsButton.find('.mejs-captions-selector').height(
  				t.captionsButton.find('.mejs-captions-selector ul').outerHeight(true) +
  				t.captionsButton.find('.mejs-captions-translations').outerHeight(true)
  			);
  		},
  
  		displayCaptions: function() {
  
  			if (typeof this.tracks == 'undefined')
  				return;
  
  			var
  				t = this,
  				i,
  				track = t.selectedTrack;
  
  			if (track != null && track.isLoaded) {
  				for (i=0; i<track.entries.times.length; i++) {
  					if (t.media.currentTime >= track.entries.times[i].start && t.media.currentTime <= track.entries.times[i].stop){
  						t.captionsText.html(track.entries.text[i]);
  						t.captions.show().height(0);
  						return; // exit out if one is visible;
  					}
  				}
  				t.captions.hide();
  			} else {
  				t.captions.hide();
  			}
  		},
  
  		displayChapters: function() {
  			var 
  				t = this,
  				i;
  
  			for (i=0; i<t.tracks.length; i++) {
  				if (t.tracks[i].kind == 'chapters' && t.tracks[i].isLoaded) {
  					t.drawChapters(t.tracks[i]);
  					t.hasChapters = true;
  					break;
  				}
  			}
  		},
  
  		drawChapters: function(chapters) {
  			var 
  				t = this,
  				i,
  				dur,
  				//width,
  				//left,
  				percent = 0,
  				usedPercent = 0;
  
  			t.chapters.empty();
  
  			for (i=0; i<chapters.entries.times.length; i++) {
  				dur = chapters.entries.times[i].stop - chapters.entries.times[i].start;
  				percent = Math.floor(dur / t.media.duration * 100);
  				if (percent + usedPercent > 100 || // too large
  					i == chapters.entries.times.length-1 && percent + usedPercent < 100) // not going to fill it in
  					{
  					percent = 100 - usedPercent;
  				}
  				//width = Math.floor(t.width * dur / t.media.duration);
  				//left = Math.floor(t.width * chapters.entries.times[i].start / t.media.duration);
  				//if (left + width > t.width) {
  				//	width = t.width - left;
  				//}
  
  				t.chapters.append( $(
  					'<div class="mejs-chapter" rel="' + chapters.entries.times[i].start + '" style="left: ' + usedPercent.toString() + '%;width: ' + percent.toString() + '%;">' + 
  						'<div class="mejs-chapter-block' + ((i==chapters.entries.times.length-1) ? ' mejs-chapter-block-last' : '') + '">' + 
  							'<span class="ch-title">' + chapters.entries.text[i] + '</span>' + 
  							'<span class="ch-time">' + mejs.Utility.secondsToTimeCode(chapters.entries.times[i].start) + '&ndash;' + mejs.Utility.secondsToTimeCode(chapters.entries.times[i].stop) + '</span>' + 
  						'</div>' +
  					'</div>'));
  				usedPercent += percent;
  			}
  
  			t.chapters.find('div.mejs-chapter').click(function() {
  				t.media.setCurrentTime( parseFloat( $(this).attr('rel') ) );
  				if (t.media.paused) {
  					t.media.play(); 
  				}
  			});
  
  			t.chapters.show();
  		}
  	});
  
  
  
  	mejs.language = {
  		codes:  {
  			af:'Afrikaans',
  			sq:'Albanian',
  			ar:'Arabic',
  			be:'Belarusian',
  			bg:'Bulgarian',
  			ca:'Catalan',
  			zh:'Chinese',
  			'zh-cn':'Chinese Simplified',
  			'zh-tw':'Chinese Traditional',
  			hr:'Croatian',
  			cs:'Czech',
  			da:'Danish',
  			nl:'Dutch',
  			en:'English',
  			et:'Estonian',
  			tl:'Filipino',
  			fi:'Finnish',
  			fr:'French',
  			gl:'Galician',
  			de:'German',
  			el:'Greek',
  			ht:'Haitian Creole',
  			iw:'Hebrew',
  			hi:'Hindi',
  			hu:'Hungarian',
  			is:'Icelandic',
  			id:'Indonesian',
  			ga:'Irish',
  			it:'Italian',
  			ja:'Japanese',
  			ko:'Korean',
  			lv:'Latvian',
  			lt:'Lithuanian',
  			mk:'Macedonian',
  			ms:'Malay',
  			mt:'Maltese',
  			no:'Norwegian',
  			fa:'Persian',
  			pl:'Polish',
  			pt:'Portuguese',
  			//'pt-pt':'Portuguese (Portugal)',
  			ro:'Romanian',
  			ru:'Russian',
  			sr:'Serbian',
  			sk:'Slovak',
  			sl:'Slovenian',
  			es:'Spanish',
  			sw:'Swahili',
  			sv:'Swedish',
  			tl:'Tagalog',
  			th:'Thai',
  			tr:'Turkish',
  			uk:'Ukrainian',
  			vi:'Vietnamese',
  			cy:'Welsh',
  			yi:'Yiddish'
  		}
  	};
  
  	/*
  	Parses WebVVT format which should be formatted as
  	================================
  	WEBVTT
  	
  	1
  	00:00:01,1 --> 00:00:05,000
  	A line of text
  
  	2
  	00:01:15,1 --> 00:02:05,000
  	A second line of text
  	
  	===============================
  
  	Adapted from: http://www.delphiki.com/html5/playr
  	*/
  	mejs.TrackFormatParser = {
  		webvvt: {
  			// match start "chapter-" (or anythingelse)
  			pattern_identifier: /^([a-zA-z]+-)?[0-9]+$/,
  			pattern_timecode: /^([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{1,3})?) --\> ([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{3})?)(.*)$/,
  
  			parse: function(trackText) {
  				var 
  					i = 0,
  					lines = mejs.TrackFormatParser.split2(trackText, /\r?\n/),
  					entries = {text:[], times:[]},
  					timecode,
  					text;
  				for(; i<lines.length; i++) {
  					// check for the line number
  					if (this.pattern_identifier.exec(lines[i])){
  						// skip to the next line where the start --> end time code should be
  						i++;
  						timecode = this.pattern_timecode.exec(lines[i]);				
  
  						if (timecode && i<lines.length){
  							i++;
  							// grab all the (possibly multi-line) text that follows
  							text = lines[i];
  							i++;
  							while(lines[i] !== '' && i<lines.length){
  								text = text + '\n' + lines[i];
  								i++;
  							}
  							text = $.trim(text).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, "<a href='$1' target='_blank'>$1</a>");
  							// Text is in a different array so I can use .join
  							entries.text.push(text);
  							entries.times.push(
  							{
  								start: (mejs.Utility.convertSMPTEtoSeconds(timecode[1]) == 0) ? 0.200 : mejs.Utility.convertSMPTEtoSeconds(timecode[1]),
  								stop: mejs.Utility.convertSMPTEtoSeconds(timecode[3]),
  								settings: timecode[5]
  							});
  						}
  					}
  				}
  				return entries;
  			}
  		},
  		// Thanks to Justin Capella: https://github.com/johndyer/mediaelement/pull/420
  		dfxp: {
  			parse: function(trackText) {
  				trackText = $(trackText).filter("tt");
  				var 
  					i = 0,
  					container = trackText.children("div").eq(0),
  					lines = container.find("p"),
  					styleNode = trackText.find("#" + container.attr("style")),
  					styles,
  					begin,
  					end,
  					text,
  					entries = {text:[], times:[]};
  
  
  				if (styleNode.length) {
  					var attributes = styleNode.removeAttr("id").get(0).attributes;
  					if (attributes.length) {
  						styles = {};
  						for (i = 0; i < attributes.length; i++) {
  							styles[attributes[i].name.split(":")[1]] = attributes[i].value;
  						}
  					}
  				}
  
  				for(i = 0; i<lines.length; i++) {
  					var style;
  					var _temp_times = {
  						start: null,
  						stop: null,
  						style: null
  					};
  					if (lines.eq(i).attr("begin")) _temp_times.start = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i).attr("begin"));
  					if (!_temp_times.start && lines.eq(i-1).attr("end")) _temp_times.start = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i-1).attr("end"));
  					if (lines.eq(i).attr("end")) _temp_times.stop = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i).attr("end"));
  					if (!_temp_times.stop && lines.eq(i+1).attr("begin")) _temp_times.stop = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i+1).attr("begin"));
  					if (styles) {
  						style = "";
  						for (var _style in styles) {
  							style += _style + ":" + styles[_style] + ";";					
  						}
  					}
  					if (style) _temp_times.style = style;
  					if (_temp_times.start == 0) _temp_times.start = 0.200;
  					entries.times.push(_temp_times);
  					text = $.trim(lines.eq(i).html()).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, "<a href='$1' target='_blank'>$1</a>");
  					entries.text.push(text);
  					if (entries.times.start == 0) entries.times.start = 2;
  				}
  				return entries;
  			}
  		},
  		split2: function (text, regex) {
  			// normal version for compliant browsers
  			// see below for IE fix
  			return text.split(regex);
  		}
  	};
  	
  	// test for browsers with bad String.split method.
  	if ('x\n\ny'.split(/\n/gi).length != 3) {
  		// add super slow IE8 and below version
  		mejs.TrackFormatParser.split2 = function(text, regex) {
  			var 
  				parts = [], 
  				chunk = '',
  				i;
  
  			for (i=0; i<text.length; i++) {
  				chunk += text.substring(i,i+1);
  				if (regex.test(chunk)) {
  					parts.push(chunk.replace(regex, ''));
  					chunk = '';
  				}
  			}
  			parts.push(chunk);
  			return parts;
  		}
  	}	
  
  })(mejs.$);
  
  /*
  * ContextMenu Plugin
  * 
  *
  */
  
  (function($) {
  
  $.extend(mejs.MepDefaults,
  	{ 'contextMenuItems': [
  		// demo of a fullscreen option
  		{ 
  			render: function(player) {
  				
  				// check for fullscreen plugin
  				if (typeof player.enterFullScreen == 'undefined')
  					return null;
  			
  				if (player.isFullScreen) {
  					return "Turn off Fullscreen";
  				} else {
  					return "Go Fullscreen";
  				}
  			},
  			click: function(player) {
  				if (player.isFullScreen) {
  					player.exitFullScreen();
  				} else {
  					player.enterFullScreen();
  				}
  			}
  		}
  		,
  		// demo of a mute/unmute button
  		{ 
  			render: function(player) {
  				if (player.media.muted) {
  					return "Unmute";
  				} else {
  					return "Mute";
  				}
  			},
  			click: function(player) {
  				if (player.media.muted) {
  					player.setMuted(false);
  				} else {
  					player.setMuted(true);
  				}
  			}
  		},
  		// separator
  		{
  			isSeparator: true
  		}
  		,
  		// demo of simple download video
  		{ 
  			render: function(player) {
  				return "Download Video";
  			},
  			click: function(player) {
  				window.location.href = player.media.currentSrc;
  			}
  		}	
  	]}
  );
  
  
  	$.extend(MediaElementPlayer.prototype, {
  		buildcontextmenu: function(player, controls, layers, media) {
  			
  			// create context menu
  			player.contextMenu = $('<div class="mejs-contextmenu"></div>')
  								.appendTo($('body'))
  								.hide();
  			
  			// create events for showing context menu
  			player.container.bind('contextmenu', function(e) {
  				if (player.isContextMenuEnabled) {
  					e.preventDefault();
  					player.renderContextMenu(e.clientX-1, e.clientY-1);
  					return false;
  				}
  			});
  			player.container.bind('click', function() {
  				player.contextMenu.hide();
  			});	
  			player.contextMenu.bind('mouseleave', function() {
  
  				//console.log('context hover out');
  				player.startContextMenuTimer();
  				
  			});		
  		},
  		
  		isContextMenuEnabled: true,
  		enableContextMenu: function() {
  			this.isContextMenuEnabled = true;
  		},
  		disableContextMenu: function() {
  			this.isContextMenuEnabled = false;
  		},
  		
  		contextMenuTimeout: null,
  		startContextMenuTimer: function() {
  			//console.log('startContextMenuTimer');
  			
  			var t = this;
  			
  			t.killContextMenuTimer();
  			
  			t.contextMenuTimer = setTimeout(function() {
  				t.hideContextMenu();
  				t.killContextMenuTimer();
  			}, 750);
  		},
  		killContextMenuTimer: function() {
  			var timer = this.contextMenuTimer;
  			
  			//console.log('killContextMenuTimer', timer);
  			
  			if (timer != null) {				
  				clearTimeout(timer);
  				delete timer;
  				timer = null;
  			}
  		},		
  		
  		hideContextMenu: function() {
  			this.contextMenu.hide();
  		},
  		
  		renderContextMenu: function(x,y) {
  			
  			// alway re-render the items so that things like "turn fullscreen on" and "turn fullscreen off" are always written correctly
  			var t = this,
  				html = '',
  				items = t.options.contextMenuItems;
  			
  			for (var i=0, il=items.length; i<il; i++) {
  				
  				if (items[i].isSeparator) {
  					html += '<div class="mejs-contextmenu-separator"></div>';
  				} else {
  				
  					var rendered = items[i].render(t);
  				
  					// render can return null if the item doesn't need to be used at the moment
  					if (rendered != null) {
  						html += '<div class="mejs-contextmenu-item" data-itemindex="' + i + '" id="element-' + (Math.random()*1000000) + '">' + rendered + '</div>';
  					}
  				}
  			}
  			
  			// position and show the context menu
  			t.contextMenu
  				.empty()
  				.append($(html))
  				.css({top:y, left:x})
  				.show();
  				
  			// bind events
  			t.contextMenu.find('.mejs-contextmenu-item').each(function() {
  							
  				// which one is this?
  				var $dom = $(this),
  					itemIndex = parseInt( $dom.data('itemindex'), 10 ),
  					item = t.options.contextMenuItems[itemIndex];
  				
  				// bind extra functionality?
  				if (typeof item.show != 'undefined')
  					item.show( $dom , t);
  				
  				// bind click action
  				$dom.click(function() {			
  					// perform click action
  					if (typeof item.click != 'undefined')
  						item.click(t);
  					
  					// close
  					t.contextMenu.hide();				
  				});				
  			});	
  			
  			// stop the controls from hiding
  			setTimeout(function() {
  				t.killControlsTimer('rev3');	
  			}, 100);
  						
  		}
  	});
  	
  })(mejs.$);
  