mediaelement 2.13.2
|
After Width: | Height: | Size: 166 B |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?>␍<!-- Generator: Adobe Fireworks CS6, Export SVG Extension by Aaron Beall (http://fireworks.abeall.com) . Version: 0.6.1 -->␍<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">␍<svg id="bigplay-gradient.fw-Page%201" viewBox="0 0 100 200" style="background-color:#ffffff00" version="1.1"␍ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"␍ x="0px" y="0px" width="100px" height="200px"␍>␍ <defs>␍ <radialGradient id="gradient1" cx="50%" cy="50%" r="50%">␍ <stop stop-color="#222222" stop-opacity="0" offset="70%"/>␍ <stop stop-color="#222222" stop-opacity="0.0118" offset="70.202%"/>␍ <stop stop-color="#333333" stop-opacity="1" offset="85%"/>␍ <stop stop-color="#333333" stop-opacity="0" offset="100%"/>␍ </radialGradient>␍ <radialGradient id="gradient2" cx="50%" cy="50%" r="50%">␍ <stop stop-color="#bbbbbb" stop-opacity="0" offset="70%"/>␍ <stop stop-color="#bbbbbb" stop-opacity="0.0118" offset="70.202%"/>␍ <stop stop-color="#bbbbbb" stop-opacity="1" offset="85%"/>␍ <stop stop-color="#bbbbbb" stop-opacity="0" offset="100%"/>␍ </radialGradient>␍ <filter id="filter1" x="-100%" y="-100%" width="300%" height="300%">␍ <!-- Glow -->␍ <feColorMatrix result="out" in="SourceGraphic" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0"/>␍ <feMorphology result="out" in="out" operator="dilate" radius="3"/>␍ <feGaussianBlur result="out" in="out" stdDeviation="1.5"/>␍ <feBlend in="SourceGraphic" in2="out" mode="normal" result="Glow1"/>␍ </filter>␍ <filter id="filter2" x="-100%" y="-100%" width="300%" height="300%">␍ <!-- Glow -->␍ <feColorMatrix result="out" in="SourceGraphic" type="matrix" values="0 0 0 0.8667 0 0 0 0 0.8667 0 0 0 0 0.8667 0 0 0 0 0.251 0"/>␍ <feMorphology result="out" in="out" operator="dilate" radius="3"/>␍ <feGaussianBlur result="out" in="out" stdDeviation="1.5"/>␍ <feBlend in="SourceGraphic" in2="out" mode="normal" result="Glow2"/>␍ </filter>␍ </defs>␍ <g id="Background">␍ </g>␍ <g id="dark%20shadow">␍ <path d="M 22 50 C 22 34.5358 34.5358 22 50 22 C 65.4642 22 78 34.5358 78 50 C 78 65.4642 65.4642 78 50 78 C 34.5358 78 22 65.4642 22 50 ZM 5 50 C 5 74.8531 25.1469 95 50 95 C 74.8531 95 95 74.8531 95 50 C 95 25.1469 74.8531 5 50 5 C 25.1469 5 5 25.1469 5 50 Z" fill="url(#gradient1)"/>␍ <path d="M 22 150 C 22 134.5358 34.5358 122 50 122 C 65.4642 122 78 134.5358 78 150 C 78 165.4642 65.4642 178 50 178 C 34.5358 178 22 165.4642 22 150 ZM 5 150 C 5 174.8531 25.1469 195 50 195 C 74.8531 195 95 174.8531 95 150 C 95 125.1469 74.8531 105 50 105 C 25.1469 105 5 125.1469 5 150 Z" fill="url(#gradient2)"/>␍ </g>␍ <g id="dark">␍ <path id="Polygon" filter="url(#filter1)" d="M 72.5 49.5 L 38.75 68.9856 L 38.75 30.0144 L 72.5 49.5 Z" fill="#ffffff"/>␍ <path id="Ellipse" d="M 13 50.5 C 13 29.7891 29.7891 13 50.5 13 C 71.2109 13 88 29.7891 88 50.5 C 88 71.2109 71.2109 88 50.5 88 C 29.7891 88 13 71.2109 13 50.5 Z" stroke="#ffffff" stroke-width="5" fill="none"/>␍ </g>␍ <g id="light">␍ <path id="Polygon2" filter="url(#filter2)" d="M 72.5 149.5 L 38.75 168.9856 L 38.75 130.0144 L 72.5 149.5 Z" fill="#ffffff"/>␍ <path id="Ellipse2" d="M 13 150.5 C 13 129.7891 29.7891 113 50.5 113 C 71.2109 113 88 129.7891 88 150.5 C 88 171.211 71.2109 188 50.5 188 C 29.7891 188 13 171.211 13 150.5 Z" stroke="#ffffff" stroke-width="5" fill="none"/>␍ </g>␍</svg>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
@@ -0,0 +1,870 @@
|
||||
.mejs-container {
|
||||
position: relative;
|
||||
background: #000;
|
||||
font-family: Helvetica, Arial;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
text-indent: 0;
|
||||
}
|
||||
|
||||
.me-plugin {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.mejs-embed, .mejs-embed body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #000;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mejs-fullscreen {
|
||||
/* set it to not show scroll bars so 100% will work */
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.mejs-container-fullscreen {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
z-index: 1000;
|
||||
}
|
||||
.mejs-container-fullscreen .mejs-mediaelement,
|
||||
.mejs-container-fullscreen video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.mejs-clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* Start: LAYERS */
|
||||
.mejs-background {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.mejs-mediaelement {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.mejs-poster {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-size: contain ;
|
||||
background-position: 50% 50% ;
|
||||
background-repeat: no-repeat ;
|
||||
}
|
||||
:root .mejs-poster img {
|
||||
display: none ;
|
||||
}
|
||||
|
||||
.mejs-poster img {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.mejs-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.mejs-overlay-play {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mejs-overlay-button {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin: -50px 0 0 -50px;
|
||||
background: url(bigplay.svg) no-repeat;
|
||||
}
|
||||
|
||||
.no-svg .mejs-overlay-button {
|
||||
background-image: url(bigplay.png);
|
||||
}
|
||||
|
||||
.mejs-overlay:hover .mejs-overlay-button {
|
||||
background-position: 0 -100px ;
|
||||
}
|
||||
|
||||
.mejs-overlay-loading {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin: -40px 0 0 -40px;
|
||||
background: #333;
|
||||
background: url(background.png);
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(50,50,50,0.9)), to(rgba(0,0,0,0.9)));
|
||||
background: -webkit-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9));
|
||||
background: -moz-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9));
|
||||
background: -o-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9));
|
||||
background: -ms-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9));
|
||||
background: linear-gradient(rgba(50,50,50,0.9), rgba(0,0,0,0.9));
|
||||
}
|
||||
|
||||
.mejs-overlay-loading span {
|
||||
display: block;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
background: transparent url(loading.gif) 50% 50% no-repeat;
|
||||
}
|
||||
|
||||
/* End: LAYERS */
|
||||
|
||||
/* Start: CONTROL BAR */
|
||||
.mejs-container .mejs-controls {
|
||||
position: absolute;
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: url(background.png);
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(50,50,50,0.7)), to(rgba(0,0,0,0.7)));
|
||||
background: -webkit-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
||||
background: -moz-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
||||
background: -o-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
||||
background: -ms-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
||||
background: linear-gradient(rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
||||
height: 30px;
|
||||
width: 100%;
|
||||
}
|
||||
.mejs-container .mejs-controls div {
|
||||
list-style-type: none;
|
||||
background-image: none;
|
||||
display: block;
|
||||
float: left;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
font-size: 11px;
|
||||
line-height: 11px;
|
||||
font-family: Helvetica, Arial;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-button button {
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
text-decoration: none;
|
||||
margin: 7px 5px;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
border: 0;
|
||||
background: transparent url(controls.svg) no-repeat;
|
||||
}
|
||||
|
||||
.no-svg .mejs-controls .mejs-button button {
|
||||
background-image: url(controls.png);
|
||||
}
|
||||
|
||||
/* :focus for accessibility */
|
||||
.mejs-controls .mejs-button button:focus {
|
||||
outline: solid 1px yellow;
|
||||
}
|
||||
|
||||
/* End: CONTROL BAR */
|
||||
|
||||
/* Start: Time (Current / Duration) */
|
||||
.mejs-container .mejs-controls .mejs-time {
|
||||
color: #fff;
|
||||
display: block;
|
||||
height: 17px;
|
||||
width: auto;
|
||||
padding: 8px 3px 0 3px ;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
-moz-box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.mejs-container .mejs-controls .mejs-time span {
|
||||
color: #fff;
|
||||
font-size: 11px;
|
||||
line-height: 12px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin: 1px 2px 0 0;
|
||||
width: auto;
|
||||
}
|
||||
/* End: Time (Current / Duration) */
|
||||
|
||||
/* Start: Play/Pause/Stop */
|
||||
.mejs-controls .mejs-play button {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-pause button {
|
||||
background-position: 0 -16px;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-stop button {
|
||||
background-position: -112px 0;
|
||||
}
|
||||
/* Start: Play/Pause/Stop */
|
||||
|
||||
/* Start: Progress Bar */
|
||||
.mejs-controls div.mejs-time-rail {
|
||||
direction: ltr;
|
||||
width: 200px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-time-rail span {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 180px;
|
||||
height: 10px;
|
||||
-webkit-border-radius: 2px;
|
||||
-moz-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-time-rail .mejs-time-total {
|
||||
margin: 5px;
|
||||
background: #333;
|
||||
background: rgba(50,50,50,0.8);
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(30,30,30,0.8)), to(rgba(60,60,60,0.8)));
|
||||
background: -webkit-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
||||
background: -moz-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
||||
background: -o-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
||||
background: -ms-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
||||
background: linear-gradient(rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-time-rail .mejs-time-buffering {
|
||||
width: 100%;
|
||||
background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
||||
background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
|
||||
background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
||||
background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
||||
background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
||||
background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
||||
-webkit-background-size: 15px 15px;
|
||||
-moz-background-size: 15px 15px;
|
||||
-o-background-size: 15px 15px;
|
||||
background-size: 15px 15px;
|
||||
-webkit-animation: buffering-stripes 2s linear infinite;
|
||||
-moz-animation: buffering-stripes 2s linear infinite;
|
||||
-ms-animation: buffering-stripes 2s linear infinite;
|
||||
-o-animation: buffering-stripes 2s linear infinite;
|
||||
animation: buffering-stripes 2s linear infinite;
|
||||
}
|
||||
|
||||
@-webkit-keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} }
|
||||
@-moz-keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} }
|
||||
@-ms-keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} }
|
||||
@-o-keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} }
|
||||
@keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} }
|
||||
|
||||
.mejs-controls .mejs-time-rail .mejs-time-loaded {
|
||||
background: #3caac8;
|
||||
background: rgba(60,170,200,0.8);
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(44,124,145,0.8)), to(rgba(78,183,212,0.8)));
|
||||
background: -webkit-linear-gradient(top, rgba(44,124,145,0.8), rgba(78,183,212,0.8));
|
||||
background: -moz-linear-gradient(top, rgba(44,124,145,0.8), rgba(78,183,212,0.8));
|
||||
background: -o-linear-gradient(top, rgba(44,124,145,0.8), rgba(78,183,212,0.8));
|
||||
background: -ms-linear-gradient(top, rgba(44,124,145,0.8), rgba(78,183,212,0.8));
|
||||
background: linear-gradient(rgba(44,124,145,0.8), rgba(78,183,212,0.8));
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-time-rail .mejs-time-current {
|
||||
background: #fff;
|
||||
background: rgba(255,255,255,0.8);
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255,255,255,0.9)), to(rgba(200,200,200,0.8)));
|
||||
background: -webkit-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
||||
background: -moz-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
||||
background: -o-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
||||
background: -ms-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
||||
background: linear-gradient(rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-time-rail .mejs-time-handle {
|
||||
display: none;
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
width: 10px;
|
||||
background: #fff;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
border: solid 2px #333;
|
||||
top: -2px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-time-rail .mejs-time-float {
|
||||
position: absolute;
|
||||
display: none;
|
||||
background: #eee;
|
||||
width: 36px;
|
||||
height: 17px;
|
||||
border: solid 1px #333;
|
||||
top: -26px;
|
||||
margin-left: -18px;
|
||||
text-align: center;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-time-rail .mejs-time-float-current {
|
||||
margin: 2px;
|
||||
width: 30px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-time-rail .mejs-time-float-corner {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
line-height: 0;
|
||||
border: solid 5px #eee;
|
||||
border-color: #eee transparent transparent transparent;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
top: 15px;
|
||||
left: 13px;
|
||||
}
|
||||
|
||||
.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float {
|
||||
width: 48px;
|
||||
}
|
||||
|
||||
.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float-current {
|
||||
width: 44px;
|
||||
}
|
||||
|
||||
.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float-corner {
|
||||
left: 18px;
|
||||
}
|
||||
|
||||
/*
|
||||
.mejs-controls .mejs-time-rail:hover .mejs-time-handle {
|
||||
visibility:visible;
|
||||
}
|
||||
*/
|
||||
/* End: Progress Bar */
|
||||
|
||||
/* Start: Fullscreen */
|
||||
.mejs-controls .mejs-fullscreen-button button {
|
||||
background-position: -32px 0;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-unfullscreen button {
|
||||
background-position: -32px -16px;
|
||||
}
|
||||
/* End: Fullscreen */
|
||||
|
||||
|
||||
/* Start: Mute/Volume */
|
||||
.mejs-controls .mejs-volume-button {
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-mute button {
|
||||
background-position: -16px -16px;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-unmute button {
|
||||
background-position: -16px 0;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-volume-button {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-volume-button .mejs-volume-slider {
|
||||
display: none;
|
||||
height: 115px;
|
||||
width: 25px;
|
||||
background: url(background.png);
|
||||
background: rgba(50, 50, 50, 0.7);
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
top: -115px;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-volume-button:hover {
|
||||
-webkit-border-radius: 0 0 4px 4px;
|
||||
-moz-border-radius: 0 0 4px 4px;
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
|
||||
/*
|
||||
.mejs-controls .mejs-volume-button:hover .mejs-volume-slider {
|
||||
display: block;
|
||||
}
|
||||
*/
|
||||
|
||||
.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-total {
|
||||
position: absolute;
|
||||
left: 11px;
|
||||
top: 8px;
|
||||
width: 2px;
|
||||
height: 100px;
|
||||
background: #ddd;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-current {
|
||||
position: absolute;
|
||||
left: 11px;
|
||||
top: 8px;
|
||||
width: 2px;
|
||||
height: 100px;
|
||||
background: #ddd;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-handle {
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
top: -3px;
|
||||
width: 16px;
|
||||
height: 6px;
|
||||
background: #ddd;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
cursor: N-resize;
|
||||
-webkit-border-radius: 1px;
|
||||
-moz-border-radius: 1px;
|
||||
border-radius: 1px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* horizontal version */
|
||||
.mejs-controls div.mejs-horizontal-volume-slider {
|
||||
height: 26px;
|
||||
width: 60px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-total {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 11px;
|
||||
width: 50px;
|
||||
height: 8px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 1px;
|
||||
-webkit-border-radius: 2px;
|
||||
-moz-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
background: #333;
|
||||
background: rgba(50,50,50,0.8);
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(30,30,30,0.8)), to(rgba(60,60,60,0.8)));
|
||||
background: -webkit-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
||||
background: -moz-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
||||
background: -o-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
||||
background: -ms-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
||||
background: linear-gradient(rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-current {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 11px;
|
||||
width: 50px;
|
||||
height: 8px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 1px;
|
||||
-webkit-border-radius: 2px;
|
||||
-moz-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
background: #fff;
|
||||
background: rgba(255,255,255,0.8);
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255,255,255,0.9)), to(rgba(200,200,200,0.8)));
|
||||
background: -webkit-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
||||
background: -moz-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
||||
background: -o-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
||||
background: -ms-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
||||
background: linear-gradient(rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-handle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* End: Mute/Volume */
|
||||
|
||||
/* Start: Track (Captions and Chapters) */
|
||||
.mejs-controls .mejs-captions-button {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-captions-button button {
|
||||
background-position: -48px 0;
|
||||
}
|
||||
.mejs-controls .mejs-captions-button .mejs-captions-selector {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
bottom: 26px;
|
||||
right: -10px;
|
||||
width: 130px;
|
||||
height: 100px;
|
||||
background: url(background.png);
|
||||
background: rgba(50,50,50,0.7);
|
||||
border: solid 1px transparent;
|
||||
padding: 10px;
|
||||
overflow: hidden;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
.mejs-controls .mejs-captions-button:hover .mejs-captions-selector {
|
||||
visibility: visible;
|
||||
}
|
||||
*/
|
||||
|
||||
.mejs-controls .mejs-captions-button .mejs-captions-selector ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
list-style-type: none !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-captions-button .mejs-captions-selector ul li {
|
||||
margin: 0 0 6px 0;
|
||||
padding: 0;
|
||||
list-style-type: none !important;
|
||||
display: block;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-captions-button .mejs-captions-selector ul li input {
|
||||
clear: both;
|
||||
float: left;
|
||||
margin: 3px 3px 0 5px;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-captions-button .mejs-captions-selector ul li label {
|
||||
width: 100px;
|
||||
float: left;
|
||||
padding: 4px 0 0 0;
|
||||
line-height: 15px;
|
||||
font-family: helvetica, arial;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-captions-button .mejs-captions-translations {
|
||||
font-size: 10px;
|
||||
margin: 0 0 5px 0;
|
||||
}
|
||||
|
||||
.mejs-chapters {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
-xborder-right: solid 1px #fff;
|
||||
width: 10000px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.mejs-chapters .mejs-chapter {
|
||||
position: absolute;
|
||||
float: left;
|
||||
background: #222;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(50,50,50,0.7)), to(rgba(0,0,0,0.7)));
|
||||
background: -webkit-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
||||
background: -moz-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
||||
background: -o-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
||||
background: -ms-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
||||
background: linear-gradient(rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
||||
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, startColorstr=#323232,endColorstr=#000000);
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.mejs-chapters .mejs-chapter .mejs-chapter-block {
|
||||
font-size: 11px;
|
||||
color: #fff;
|
||||
padding: 5px;
|
||||
display: block;
|
||||
border-right: solid 1px #333;
|
||||
border-bottom: solid 1px #333;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mejs-chapters .mejs-chapter .mejs-chapter-block-last {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.mejs-chapters .mejs-chapter .mejs-chapter-block:hover {
|
||||
background: #666;
|
||||
background: rgba(102,102,102, 0.7);
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(102,102,102,0.7)), to(rgba(50,50,50,0.6)));
|
||||
background: -webkit-linear-gradient(top, rgba(102,102,102,0.7), rgba(50,50,50,0.6));
|
||||
background: -moz-linear-gradient(top, rgba(102,102,102,0.7), rgba(50,50,50,0.6));
|
||||
background: -o-linear-gradient(top, rgba(102,102,102,0.7), rgba(50,50,50,0.6));
|
||||
background: -ms-linear-gradient(top, rgba(102,102,102,0.7), rgba(50,50,50,0.6));
|
||||
background: linear-gradient(rgba(102,102,102,0.7), rgba(50,50,50,0.6));
|
||||
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, startColorstr=#666666,endColorstr=#323232);
|
||||
}
|
||||
|
||||
.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-title {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
margin: 0 0 3px 0;
|
||||
line-height: 12px;
|
||||
}
|
||||
|
||||
.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-timespan {
|
||||
font-size: 12px;
|
||||
line-height: 12px;
|
||||
margin: 3px 0 4px 0;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.mejs-captions-layer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
text-align:center;
|
||||
line-height: 22px;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.mejs-captions-layer a {
|
||||
color: #fff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.mejs-captions-layer[lang=ar] {
|
||||
font-size: 20px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.mejs-captions-position {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 15px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.mejs-captions-position-hover {
|
||||
bottom: 45px;
|
||||
}
|
||||
|
||||
.mejs-captions-text {
|
||||
padding: 3px 5px;
|
||||
background: url(background.png);
|
||||
background: rgba(20, 20, 20, 0.8);
|
||||
|
||||
}
|
||||
/* End: Track (Captions and Chapters) */
|
||||
|
||||
/* Start: Error */
|
||||
.me-cannotplay {
|
||||
}
|
||||
|
||||
.me-cannotplay a {
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.me-cannotplay span {
|
||||
padding: 15px;
|
||||
display: block;
|
||||
}
|
||||
/* End: Error */
|
||||
|
||||
|
||||
/* Start: Loop */
|
||||
.mejs-controls .mejs-loop-off button {
|
||||
background-position: -64px -16px;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-loop-on button {
|
||||
background-position: -64px 0;
|
||||
}
|
||||
|
||||
/* End: Loop */
|
||||
|
||||
/* Start: backlight */
|
||||
.mejs-controls .mejs-backlight-off button {
|
||||
background-position: -80px -16px;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-backlight-on button {
|
||||
background-position: -80px 0;
|
||||
}
|
||||
/* End: backlight */
|
||||
|
||||
/* Start: Picture Controls */
|
||||
.mejs-controls .mejs-picturecontrols-button {
|
||||
background-position: -96px 0;
|
||||
}
|
||||
/* End: Picture Controls */
|
||||
|
||||
|
||||
/* context menu */
|
||||
.mejs-contextmenu {
|
||||
position: absolute;
|
||||
width: 150px;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: #fff;
|
||||
border: solid 1px #999;
|
||||
z-index: 1001; /* make sure it shows on fullscreen */
|
||||
}
|
||||
.mejs-contextmenu .mejs-contextmenu-separator {
|
||||
height: 1px;
|
||||
font-size: 0;
|
||||
margin: 5px 6px;
|
||||
background: #333;
|
||||
}
|
||||
|
||||
.mejs-contextmenu .mejs-contextmenu-item {
|
||||
font-family: Helvetica, Arial;
|
||||
font-size: 12px;
|
||||
padding: 4px 6px;
|
||||
cursor: pointer;
|
||||
color: #333;
|
||||
}
|
||||
.mejs-contextmenu .mejs-contextmenu-item:hover {
|
||||
background: #2C7C91;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Start: Source Chooser */
|
||||
.mejs-controls .mejs-sourcechooser-button {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-sourcechooser-button button {
|
||||
background-position: -128px 0;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
bottom: 26px;
|
||||
right: -10px;
|
||||
width: 130px;
|
||||
height: 100px;
|
||||
background: url(background.png);
|
||||
background: rgba(50,50,50,0.7);
|
||||
border: solid 1px transparent;
|
||||
padding: 10px;
|
||||
overflow: hidden;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
list-style-type: none !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li {
|
||||
margin: 0 0 6px 0;
|
||||
padding: 0;
|
||||
list-style-type: none !important;
|
||||
display: block;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li input {
|
||||
clear: both;
|
||||
float: left;
|
||||
margin: 3px 3px 0 5px;
|
||||
}
|
||||
|
||||
.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li label {
|
||||
width: 100px;
|
||||
float: left;
|
||||
padding: 4px 0 0 0;
|
||||
line-height: 15px;
|
||||
font-family: helvetica, arial;
|
||||
font-size: 10px;
|
||||
}
|
||||
/* End: Source Chooser */
|
||||
|
||||
/* Start: Postroll */
|
||||
.mejs-postroll-layer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url(background.png);
|
||||
background: rgba(50,50,50,0.7);
|
||||
z-index: 1000;
|
||||
overflow: hidden;
|
||||
}
|
||||
.mejs-postroll-layer-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.mejs-postroll-close {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
background: url(background.png);
|
||||
background: rgba(50,50,50,0.7);
|
||||
color: #fff;
|
||||
padding: 4px;
|
||||
z-index: 100;
|
||||
cursor: pointer;
|
||||
}
|
||||
/* End: Postroll */
|
||||
@@ -0,0 +1,289 @@
|
||||
/* TED player */
|
||||
.mejs-container.mejs-ted {
|
||||
|
||||
}
|
||||
.mejs-ted .mejs-controls {
|
||||
background: #eee;
|
||||
height: 65px;
|
||||
}
|
||||
|
||||
.mejs-ted .mejs-button,
|
||||
.mejs-ted .mejs-time {
|
||||
position: absolute;
|
||||
background: #ddd;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-total {
|
||||
background-color: none;
|
||||
background: url(controls-ted.png) repeat-x 0 -52px;
|
||||
height: 6px;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-buffering {
|
||||
height: 6px;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-loaded {
|
||||
background-color: none;
|
||||
background: url(controls-ted.png) repeat-x 0 -52px;
|
||||
width: 0;
|
||||
height: 6px;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-current {
|
||||
width: 0;
|
||||
height: 6px;
|
||||
background-color: none;
|
||||
background: url(controls-ted.png) repeat-x 0 -59px;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-handle {
|
||||
display: block;
|
||||
margin: 0;
|
||||
width: 14px;
|
||||
height: 21px;
|
||||
top: -7px;
|
||||
border: 0;
|
||||
background: url(controls-ted.png) no-repeat 0 0;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-float {
|
||||
display: none;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-playpause-button {
|
||||
top: 29px;
|
||||
left: 9px;
|
||||
width: 49px;
|
||||
height: 28px;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-playpause-button button {
|
||||
width: 49px;
|
||||
height: 28px;
|
||||
background: url(controls-ted.png) no-repeat -50px -23px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-pause button {
|
||||
background-position: 0 -23px;
|
||||
}
|
||||
|
||||
.mejs-ted .mejs-controls .mejs-fullscreen-button {
|
||||
top: 34px;
|
||||
right: 9px;
|
||||
width: 17px;
|
||||
height: 15px;
|
||||
background : none;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-fullscreen-button button {
|
||||
width: 19px;
|
||||
height: 17px;
|
||||
background: transparent url(controls-ted.png) no-repeat 0 -66px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-unfullscreen button {
|
||||
background: transparent url(controls-ted.png) no-repeat -21px -66px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-volume-button {
|
||||
top: 30px;
|
||||
right: 35px;
|
||||
width: 24px;
|
||||
height: 22px;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-mute button {
|
||||
background: url(controls-ted.png) no-repeat -15px 0;
|
||||
width: 24px;
|
||||
height: 22px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-unmute button {
|
||||
background: url(controls-ted.png) no-repeat -40px 0;
|
||||
width: 24px;
|
||||
height: 22px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-slider {
|
||||
background: #fff;
|
||||
border: solid 1px #aaa;
|
||||
border-width: 1px 1px 0 1px;
|
||||
width: 22px;
|
||||
height: 65px;
|
||||
top: -65px;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-total {
|
||||
background: url(controls-ted.png) repeat-y -41px -66px;
|
||||
left: 8px;
|
||||
width: 6px;
|
||||
height: 50px;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-current {
|
||||
left: 8px;
|
||||
width: 6px;
|
||||
background: url(controls-ted.png) repeat-y -48px -66px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-handle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mejs-ted .mejs-controls .mejs-time span {
|
||||
color: #333;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-currenttime-container {
|
||||
position: absolute;
|
||||
top: 32px;
|
||||
right: 100px;
|
||||
border: solid 1px #999;
|
||||
background: #fff;
|
||||
color: #333;
|
||||
padding-top: 2px;
|
||||
border-radius: 3px;
|
||||
color: #333;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-duration-container {
|
||||
|
||||
position: absolute;
|
||||
top: 32px;
|
||||
right: 65px;
|
||||
border: solid 1px #999;
|
||||
background: #fff;
|
||||
color: #333;
|
||||
padding-top: 2px;
|
||||
border-radius: 3px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.mejs-ted .mejs-controls .mejs-time button{
|
||||
color: #333;
|
||||
}
|
||||
.mejs-ted .mejs-controls .mejs-captions-button {
|
||||
display: none;
|
||||
}
|
||||
/* END: TED player */
|
||||
|
||||
|
||||
/* WMP player */
|
||||
.mejs-container.mejs-wmp {
|
||||
|
||||
}
|
||||
.mejs-wmp .mejs-controls {
|
||||
background: transparent url(controls-wmp-bg.png) center 16px no-repeat;
|
||||
height: 65px;
|
||||
}
|
||||
|
||||
.mejs-wmp .mejs-button,
|
||||
.mejs-wmp .mejs-time {
|
||||
position: absolute;
|
||||
background: transparent;
|
||||
}
|
||||
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-total {
|
||||
background-color: transparent;
|
||||
border: solid 1px #ccc;
|
||||
height: 3px;
|
||||
}
|
||||
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-buffering {
|
||||
height: 3px;
|
||||
}
|
||||
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-loaded {
|
||||
background-color: rgba(255,255,255,0.3);
|
||||
width: 0;
|
||||
height: 3px;
|
||||
}
|
||||
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-current {
|
||||
width: 0;
|
||||
height: 1px;
|
||||
background-color: #014CB6;
|
||||
border: solid 1px #7FC9FA;
|
||||
border-width: 1px 0;
|
||||
border-color: #7FC9FA #fff #619FF2 #fff;
|
||||
}
|
||||
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-handle {
|
||||
display: block;
|
||||
margin: 0;
|
||||
width: 16px;
|
||||
height: 9px;
|
||||
top: -3px;
|
||||
border: 0;
|
||||
background: url(controls-wmp.png) no-repeat 0 -80px;
|
||||
}
|
||||
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-float {
|
||||
display: none;
|
||||
}
|
||||
.mejs-wmp .mejs-controls .mejs-playpause-button {
|
||||
top: 10px;
|
||||
left: 50%;
|
||||
margin: 10px 0 0 -20px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
|
||||
}
|
||||
.mejs-wmp .mejs-controls .mejs-playpause-button button {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: url(controls-wmp.png) no-repeat 0 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.mejs-wmp .mejs-controls .mejs-pause button {
|
||||
background-position: 0 -40px;
|
||||
}
|
||||
|
||||
.mejs-wmp .mejs-controls .mejs-currenttime-container {
|
||||
position: absolute;
|
||||
top: 25px;
|
||||
left: 50%;
|
||||
margin-left: -93px;
|
||||
}
|
||||
.mejs-wmp .mejs-controls .mejs-duration-container {
|
||||
position: absolute;
|
||||
top: 25px;
|
||||
left: 50%;
|
||||
margin-left: -58px;
|
||||
}
|
||||
|
||||
|
||||
.mejs-wmp .mejs-controls .mejs-volume-button {
|
||||
top: 32px;
|
||||
right: 50%;
|
||||
margin-right: -55px;
|
||||
width: 20px;
|
||||
height: 15px;
|
||||
}
|
||||
.mejs-wmp .mejs-controls .mejs-volume-button button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: url(controls-wmp.png) no-repeat -42px -17px;
|
||||
width: 20px;
|
||||
height: 15px;
|
||||
}
|
||||
.mejs-wmp .mejs-controls .mejs-unmute button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: url(controls-wmp.png) no-repeat -42px 0;
|
||||
width: 20px;
|
||||
height: 15px;
|
||||
}
|
||||
.mejs-wmp .mejs-controls .mejs-volume-button .mejs-volume-slider {
|
||||
background: rgba(102,102,102,0.6);
|
||||
}
|
||||
|
||||
.mejs-wmp .mejs-controls .mejs-fullscreen-button {
|
||||
top: 32px;
|
||||
right: 50%;
|
||||
margin-right: -82px;
|
||||
width: 15px;
|
||||
height: 14px;
|
||||
}
|
||||
.mejs-wmp .mejs-controls .mejs-fullscreen-button button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: url(controls-wmp.png) no-repeat -63px 0;
|
||||
width: 15px;
|
||||
height: 14px;
|
||||
}
|
||||
.mejs-wmp .mejs-controls .mejs-captions-button {
|
||||
display: none;
|
||||
}
|
||||
/* END: WMP player */
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
(function($) {
|
||||
|
||||
// borrowed from jQuery (no deep, bad fake object detection)
|
||||
$.ender({extend: function() {
|
||||
var options, name, src, copy,
|
||||
target = arguments[0] || {},
|
||||
i = 1,
|
||||
length = arguments.length;
|
||||
|
||||
// Handle case when target is a string or something (possible in deep copy)
|
||||
if ( typeof target !== "object" && typeof target !== "function" ) {
|
||||
target = {};
|
||||
}
|
||||
|
||||
for ( ; i < length; i++ ) {
|
||||
// Only deal with non-null/undefined values
|
||||
if ( (options = arguments[ i ]) != null ) {
|
||||
// Extend the base object
|
||||
for ( name in options ) {
|
||||
src = target[ name ];
|
||||
copy = options[ name ];
|
||||
|
||||
// Prevent never-ending loop
|
||||
if ( target === copy ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( copy !== undefined ) {
|
||||
target[ name ] = copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the modified object
|
||||
return target;
|
||||
}});
|
||||
|
||||
// outerWidth
|
||||
$.ender({outerWidth: function(margin) {
|
||||
var fp = parseFloat;
|
||||
return fp(this.width())
|
||||
+ (margin ? fp(this.css('margin-left')) + fp(this.css('margin-right')) : 0)
|
||||
+ fp(this.css('padding-left'))+ fp(this.css('padding-right'))
|
||||
+ fp(this.css('border-left-width')) + fp(this.css('border-right-width'))
|
||||
;
|
||||
}}, true);
|
||||
|
||||
})(ender);
|
||||
@@ -0,0 +1,136 @@
|
||||
// necessary detection (fixes for <IE9)
|
||||
mejs.MediaFeatures = {
|
||||
init: function() {
|
||||
var
|
||||
t = this,
|
||||
d = document,
|
||||
nav = mejs.PluginDetector.nav,
|
||||
ua = mejs.PluginDetector.ua.toLowerCase(),
|
||||
i,
|
||||
v,
|
||||
html5Elements = ['source','track','audio','video'];
|
||||
|
||||
// detect browsers (only the ones that have some kind of quirk we need to work around)
|
||||
t.isiPad = (ua.match(/ipad/i) !== null);
|
||||
t.isiPhone = (ua.match(/iphone/i) !== null);
|
||||
t.isiOS = t.isiPhone || t.isiPad;
|
||||
t.isAndroid = (ua.match(/android/i) !== null);
|
||||
t.isBustedAndroid = (ua.match(/android 2\.[12]/) !== null);
|
||||
t.isBustedNativeHTTPS = (location.protocol === 'https:' && (ua.match(/android [12]\./) !== null || ua.match(/macintosh.* version.* safari/) !== null));
|
||||
t.isIE = (nav.appName.toLowerCase().indexOf("microsoft") != -1 || nav.appName.toLowerCase().match(/trident/gi) !== null);
|
||||
t.isChrome = (ua.match(/chrome/gi) !== null);
|
||||
t.isFirefox = (ua.match(/firefox/gi) !== null);
|
||||
t.isWebkit = (ua.match(/webkit/gi) !== null);
|
||||
t.isGecko = (ua.match(/gecko/gi) !== null) && !t.isWebkit && !t.isIE;
|
||||
t.isOpera = (ua.match(/opera/gi) !== null);
|
||||
t.hasTouch = ('ontouchstart' in window); // && window.ontouchstart != null); // this breaks iOS 7
|
||||
|
||||
// borrowed from Modernizr
|
||||
t.svg = !! document.createElementNS &&
|
||||
!! document.createElementNS('http://www.w3.org/2000/svg','svg').createSVGRect;
|
||||
|
||||
// create HTML5 media elements for IE before 9, get a <video> element for fullscreen detection
|
||||
for (i=0; i<html5Elements.length; i++) {
|
||||
v = document.createElement(html5Elements[i]);
|
||||
}
|
||||
|
||||
t.supportsMediaTag = (typeof v.canPlayType !== 'undefined' || t.isBustedAndroid);
|
||||
|
||||
// Fix for IE9 on Windows 7N / Windows 7KN (Media Player not installer)
|
||||
try{
|
||||
v.canPlayType("video/mp4");
|
||||
}catch(e){
|
||||
t.supportsMediaTag = false;
|
||||
}
|
||||
|
||||
// detect native JavaScript fullscreen (Safari/Firefox only, Chrome still fails)
|
||||
|
||||
// iOS
|
||||
t.hasSemiNativeFullScreen = (typeof v.webkitEnterFullscreen !== 'undefined');
|
||||
|
||||
// W3C
|
||||
t.hasNativeFullscreen = (typeof v.requestFullscreen !== 'undefined');
|
||||
|
||||
// webkit/firefox/IE11+
|
||||
t.hasWebkitNativeFullScreen = (typeof v.webkitRequestFullScreen !== 'undefined');
|
||||
t.hasMozNativeFullScreen = (typeof v.mozRequestFullScreen !== 'undefined');
|
||||
t.hasMsNativeFullScreen = (typeof v.msRequestFullscreen !== 'undefined');
|
||||
|
||||
t.hasTrueNativeFullScreen = (t.hasWebkitNativeFullScreen || t.hasMozNativeFullScreen || t.hasMsNativeFullScreen);
|
||||
t.nativeFullScreenEnabled = t.hasTrueNativeFullScreen;
|
||||
|
||||
// Enabled?
|
||||
if (t.hasMozNativeFullScreen) {
|
||||
t.nativeFullScreenEnabled = document.mozFullScreenEnabled;
|
||||
} else if (t.hasMsNativeFullScreen) {
|
||||
t.nativeFullScreenEnabled = document.msFullscreenEnabled;
|
||||
}
|
||||
|
||||
if (t.isChrome) {
|
||||
t.hasSemiNativeFullScreen = false;
|
||||
}
|
||||
|
||||
if (t.hasTrueNativeFullScreen) {
|
||||
|
||||
t.fullScreenEventName = '';
|
||||
if (t.hasWebkitNativeFullScreen) {
|
||||
t.fullScreenEventName = 'webkitfullscreenchange';
|
||||
|
||||
} else if (t.hasMozNativeFullScreen) {
|
||||
t.fullScreenEventName = 'mozfullscreenchange';
|
||||
|
||||
} else if (t.hasMsNativeFullScreen) {
|
||||
t.fullScreenEventName = 'MSFullscreenChange';
|
||||
}
|
||||
|
||||
t.isFullScreen = function() {
|
||||
if (v.mozRequestFullScreen) {
|
||||
return d.mozFullScreen;
|
||||
|
||||
} else if (v.webkitRequestFullScreen) {
|
||||
return d.webkitIsFullScreen;
|
||||
|
||||
} else if (v.hasMsNativeFullScreen) {
|
||||
return d.msFullscreenElement !== null;
|
||||
}
|
||||
}
|
||||
|
||||
t.requestFullScreen = function(el) {
|
||||
|
||||
if (t.hasWebkitNativeFullScreen) {
|
||||
el.webkitRequestFullScreen();
|
||||
|
||||
} else if (t.hasMozNativeFullScreen) {
|
||||
el.mozRequestFullScreen();
|
||||
|
||||
} else if (t.hasMsNativeFullScreen) {
|
||||
el.msRequestFullscreen();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
t.cancelFullScreen = function() {
|
||||
if (t.hasWebkitNativeFullScreen) {
|
||||
document.webkitCancelFullScreen();
|
||||
|
||||
} else if (t.hasMozNativeFullScreen) {
|
||||
document.mozCancelFullScreen();
|
||||
|
||||
} else if (t.hasMsNativeFullScreen) {
|
||||
document.msExitFullscreen();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// OS X 10.5 can't do this even if it says it can :(
|
||||
if (t.hasSemiNativeFullScreen && ua.match(/mac os x 10_5/i)) {
|
||||
t.hasNativeFullScreen = false;
|
||||
t.hasSemiNativeFullScreen = false;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
mejs.MediaFeatures.init();
|
||||
@@ -0,0 +1,13 @@
|
||||
/*!
|
||||
* MediaElement.js
|
||||
* HTML5 <video> and <audio> shim and player
|
||||
* http://mediaelementjs.com/
|
||||
*
|
||||
* Creates a JavaScript object that mimics HTML5 MediaElement API
|
||||
* for browsers that don't understand HTML5 or can't play the provided codec
|
||||
* Can play MP4 (H.264), Ogg, WebM, FLV, WMV, WMA, ACC, and MP3
|
||||
*
|
||||
* Copyright 2010-2013, John Dyer (http://j.hn)
|
||||
* License: MIT
|
||||
*
|
||||
*/
|
||||
@@ -0,0 +1,28 @@
|
||||
/*!
|
||||
* This is a i18n.locale language object.
|
||||
*
|
||||
* German translation by Tim Latz, latz.tim@gmail.com
|
||||
*
|
||||
* @author
|
||||
* Tim Latz (latz.tim@gmail.com)
|
||||
*
|
||||
* @see
|
||||
* me-i18n.js
|
||||
*
|
||||
* @params
|
||||
* - exports - CommonJS, window ..
|
||||
*/
|
||||
;(function(exports, undefined) {
|
||||
|
||||
"use strict";
|
||||
|
||||
if (typeof exports.de === 'undefined') {
|
||||
exports.de = {
|
||||
"Fullscreen" : "Vollbild",
|
||||
"Go Fullscreen" : "Vollbild an",
|
||||
"Turn off Fullscreen" : "Vollbild aus",
|
||||
"Close" : "Schließen"
|
||||
};
|
||||
}
|
||||
|
||||
}(mejs.i18n.locale.strings));
|
||||
@@ -0,0 +1,28 @@
|
||||
/*!
|
||||
* This is a i18n.locale language object.
|
||||
*
|
||||
* Traditional chinese translation by Tim Latz, latz.tim@gmail.com
|
||||
*
|
||||
* @author
|
||||
* Tim Latz (latz.tim@gmail.com)
|
||||
*
|
||||
* @see
|
||||
* me-i18n.js
|
||||
*
|
||||
* @params
|
||||
* - exports - CommonJS, window ..
|
||||
*/
|
||||
;(function(exports, undefined) {
|
||||
|
||||
"use strict";
|
||||
|
||||
if (typeof exports.zh === 'undefined') {
|
||||
exports.zh = {
|
||||
"Fullscreen" : "全螢幕",
|
||||
"Go Fullscreen" : "全屏模式",
|
||||
"Turn off Fullscreen" : "退出全屏模式",
|
||||
"Close" : "關閉"
|
||||
};
|
||||
}
|
||||
|
||||
}(mejs.i18n.locale.strings));
|
||||
@@ -0,0 +1,153 @@
|
||||
/*!
|
||||
* Adds Internationalization and localization to mediaelement.
|
||||
*
|
||||
* This file does not contain translations, you have to add the manually.
|
||||
* The schema is always the same: me-i18n-locale-[ISO_639-1 Code].js
|
||||
*
|
||||
* Examples are provided both for german and chinese translation.
|
||||
*
|
||||
*
|
||||
* What is the concept beyond i18n?
|
||||
* http://en.wikipedia.org/wiki/Internationalization_and_localization
|
||||
*
|
||||
* What langcode should i use?
|
||||
* http://en.wikipedia.org/wiki/ISO_639-1
|
||||
*
|
||||
*
|
||||
* License?
|
||||
*
|
||||
* The i18n file uses methods from the Drupal project (drupal.js):
|
||||
* - i18n.methods.t() (modified)
|
||||
* - i18n.methods.checkPlain() (full copy)
|
||||
*
|
||||
* The Drupal project is (like mediaelementjs) licensed under GPLv2.
|
||||
* - http://drupal.org/licensing/faq/#q1
|
||||
* - https://github.com/johndyer/mediaelement
|
||||
* - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
*
|
||||
* @author
|
||||
* Tim Latz (latz.tim@gmail.com)
|
||||
*
|
||||
*
|
||||
* @params
|
||||
* - context - document, iframe ..
|
||||
* - exports - CommonJS, window ..
|
||||
*
|
||||
*/
|
||||
;(function(context, exports, undefined) {
|
||||
"use strict";
|
||||
var i18n = {
|
||||
"locale": {
|
||||
"language" : '',
|
||||
"strings" : {}
|
||||
},
|
||||
"methods" : {}
|
||||
};
|
||||
// start i18n
|
||||
|
||||
|
||||
/**
|
||||
* Get language, fallback to browser's language if empty
|
||||
*/
|
||||
i18n.getLanguage = function () {
|
||||
var language = i18n.locale.language || window.navigator.userLanguage || window.navigator.language;
|
||||
// convert to iso 639-1 (2-letters, lower case)
|
||||
return language.substr(0, 2).toLowerCase();
|
||||
};
|
||||
|
||||
// i18n fixes for compatibility with WordPress
|
||||
if ( typeof mejsL10n != 'undefined' ) {
|
||||
i18n.locale.language = mejsL10n.language;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encode special characters in a plain-text string for display as HTML.
|
||||
*/
|
||||
i18n.methods.checkPlain = function (str) {
|
||||
var character, regex,
|
||||
replace = {
|
||||
'&': '&',
|
||||
'"': '"',
|
||||
'<': '<',
|
||||
'>': '>'
|
||||
};
|
||||
str = String(str);
|
||||
for (character in replace) {
|
||||
if (replace.hasOwnProperty(character)) {
|
||||
regex = new RegExp(character, 'g');
|
||||
str = str.replace(regex, replace[character]);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
};
|
||||
|
||||
/**
|
||||
* Translate strings to the page language or a given language.
|
||||
*
|
||||
*
|
||||
* @param str
|
||||
* A string containing the English string to translate.
|
||||
*
|
||||
* @param options
|
||||
* - 'context' (defaults to the default context): The context the source string
|
||||
* belongs to.
|
||||
*
|
||||
* @return
|
||||
* The translated string, escaped via i18n.methods.checkPlain()
|
||||
*/
|
||||
i18n.methods.t = function (str, options) {
|
||||
|
||||
// Fetch the localized version of the string.
|
||||
if (i18n.locale.strings && i18n.locale.strings[options.context] && i18n.locale.strings[options.context][str]) {
|
||||
str = i18n.locale.strings[options.context][str];
|
||||
}
|
||||
|
||||
return i18n.methods.checkPlain(str);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper for i18n.methods.t()
|
||||
*
|
||||
* @see i18n.methods.t()
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
i18n.t = function(str, options) {
|
||||
|
||||
if (typeof str === 'string' && str.length > 0) {
|
||||
|
||||
// check every time due language can change for
|
||||
// different reasons (translation, lang switcher ..)
|
||||
var language = i18n.getLanguage();
|
||||
|
||||
options = options || {
|
||||
"context" : language
|
||||
};
|
||||
|
||||
return i18n.methods.t(str, options);
|
||||
}
|
||||
else {
|
||||
throw {
|
||||
"name" : 'InvalidArgumentException',
|
||||
"message" : 'First argument is either not a string or empty.'
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// end i18n
|
||||
exports.i18n = i18n;
|
||||
}(document, mejs));
|
||||
|
||||
// i18n fixes for compatibility with WordPress
|
||||
;(function(exports, undefined) {
|
||||
|
||||
"use strict";
|
||||
|
||||
if ( typeof mejsL10n != 'undefined' ) {
|
||||
exports[mejsL10n.language] = mejsL10n.strings;
|
||||
}
|
||||
|
||||
}(mejs.i18n.locale.strings));
|
||||
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
extension methods to <video> or <audio> object to bring it into parity with PluginMediaElement (see below)
|
||||
*/
|
||||
mejs.HtmlMediaElement = {
|
||||
pluginType: 'native',
|
||||
isFullScreen: false,
|
||||
|
||||
setCurrentTime: function (time) {
|
||||
this.currentTime = time;
|
||||
},
|
||||
|
||||
setMuted: function (muted) {
|
||||
this.muted = muted;
|
||||
},
|
||||
|
||||
setVolume: function (volume) {
|
||||
this.volume = volume;
|
||||
},
|
||||
|
||||
// for parity with the plugin versions
|
||||
stop: function () {
|
||||
this.pause();
|
||||
},
|
||||
|
||||
// This can be a url string
|
||||
// or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}]
|
||||
setSrc: function (url) {
|
||||
|
||||
// Fix for IE9 which can't set .src when there are <source> elements. Awesome, right?
|
||||
var
|
||||
existingSources = this.getElementsByTagName('source');
|
||||
while (existingSources.length > 0){
|
||||
this.removeChild(existingSources[0]);
|
||||
}
|
||||
|
||||
if (typeof url == 'string') {
|
||||
this.src = url;
|
||||
} else {
|
||||
var i, media;
|
||||
|
||||
for (i=0; i<url.length; i++) {
|
||||
media = url[i];
|
||||
if (this.canPlayType(media.type)) {
|
||||
this.src = media.src;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setVideoSize: function (width, height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Mimics the <video/audio> element by calling Flash's External Interface or Silverlights [ScriptableMember]
|
||||
*/
|
||||
mejs.PluginMediaElement = function (pluginid, pluginType, mediaUrl) {
|
||||
this.id = pluginid;
|
||||
this.pluginType = pluginType;
|
||||
this.src = mediaUrl;
|
||||
this.events = {};
|
||||
this.attributes = {};
|
||||
};
|
||||
|
||||
// JavaScript values and ExternalInterface methods that match HTML5 video properties methods
|
||||
// http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/fl/video/FLVPlayback.html
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
|
||||
mejs.PluginMediaElement.prototype = {
|
||||
|
||||
// special
|
||||
pluginElement: null,
|
||||
pluginType: '',
|
||||
isFullScreen: false,
|
||||
|
||||
// not implemented :(
|
||||
playbackRate: -1,
|
||||
defaultPlaybackRate: -1,
|
||||
seekable: [],
|
||||
played: [],
|
||||
|
||||
// HTML5 read-only properties
|
||||
paused: true,
|
||||
ended: false,
|
||||
seeking: false,
|
||||
duration: 0,
|
||||
error: null,
|
||||
tagName: '',
|
||||
|
||||
// HTML5 get/set properties, but only set (updated by event handlers)
|
||||
muted: false,
|
||||
volume: 1,
|
||||
currentTime: 0,
|
||||
|
||||
// HTML5 methods
|
||||
play: function () {
|
||||
if (this.pluginApi != null) {
|
||||
if (this.pluginType == 'youtube') {
|
||||
this.pluginApi.playVideo();
|
||||
} else {
|
||||
this.pluginApi.playMedia();
|
||||
}
|
||||
this.paused = false;
|
||||
}
|
||||
},
|
||||
load: function () {
|
||||
if (this.pluginApi != null) {
|
||||
if (this.pluginType == 'youtube') {
|
||||
} else {
|
||||
this.pluginApi.loadMedia();
|
||||
}
|
||||
|
||||
this.paused = false;
|
||||
}
|
||||
},
|
||||
pause: function () {
|
||||
if (this.pluginApi != null) {
|
||||
if (this.pluginType == 'youtube') {
|
||||
this.pluginApi.pauseVideo();
|
||||
} else {
|
||||
this.pluginApi.pauseMedia();
|
||||
}
|
||||
|
||||
|
||||
this.paused = true;
|
||||
}
|
||||
},
|
||||
stop: function () {
|
||||
if (this.pluginApi != null) {
|
||||
if (this.pluginType == 'youtube') {
|
||||
this.pluginApi.stopVideo();
|
||||
} else {
|
||||
this.pluginApi.stopMedia();
|
||||
}
|
||||
this.paused = true;
|
||||
}
|
||||
},
|
||||
canPlayType: function(type) {
|
||||
var i,
|
||||
j,
|
||||
pluginInfo,
|
||||
pluginVersions = mejs.plugins[this.pluginType];
|
||||
|
||||
for (i=0; i<pluginVersions.length; i++) {
|
||||
pluginInfo = pluginVersions[i];
|
||||
|
||||
// test if user has the correct plugin version
|
||||
if (mejs.PluginDetector.hasPluginVersion(this.pluginType, pluginInfo.version)) {
|
||||
|
||||
// test for plugin playback types
|
||||
for (j=0; j<pluginInfo.types.length; j++) {
|
||||
// find plugin that can play the type
|
||||
if (type == pluginInfo.types[j]) {
|
||||
return 'probably';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
|
||||
positionFullscreenButton: function(x,y,visibleAndAbove) {
|
||||
if (this.pluginApi != null && this.pluginApi.positionFullscreenButton) {
|
||||
this.pluginApi.positionFullscreenButton(Math.floor(x),Math.floor(y),visibleAndAbove);
|
||||
}
|
||||
},
|
||||
|
||||
hideFullscreenButton: function() {
|
||||
if (this.pluginApi != null && this.pluginApi.hideFullscreenButton) {
|
||||
this.pluginApi.hideFullscreenButton();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// custom methods since not all JavaScript implementations support get/set
|
||||
|
||||
// This can be a url string
|
||||
// or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}]
|
||||
setSrc: function (url) {
|
||||
if (typeof url == 'string') {
|
||||
this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(url));
|
||||
this.src = mejs.Utility.absolutizeUrl(url);
|
||||
} else {
|
||||
var i, media;
|
||||
|
||||
for (i=0; i<url.length; i++) {
|
||||
media = url[i];
|
||||
if (this.canPlayType(media.type)) {
|
||||
this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(media.src));
|
||||
this.src = mejs.Utility.absolutizeUrl(url);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
setCurrentTime: function (time) {
|
||||
if (this.pluginApi != null) {
|
||||
if (this.pluginType == 'youtube') {
|
||||
this.pluginApi.seekTo(time);
|
||||
} else {
|
||||
this.pluginApi.setCurrentTime(time);
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.currentTime = time;
|
||||
}
|
||||
},
|
||||
setVolume: function (volume) {
|
||||
if (this.pluginApi != null) {
|
||||
// same on YouTube and MEjs
|
||||
if (this.pluginType == 'youtube') {
|
||||
this.pluginApi.setVolume(volume * 100);
|
||||
} else {
|
||||
this.pluginApi.setVolume(volume);
|
||||
}
|
||||
this.volume = volume;
|
||||
}
|
||||
},
|
||||
setMuted: function (muted) {
|
||||
if (this.pluginApi != null) {
|
||||
if (this.pluginType == 'youtube') {
|
||||
if (muted) {
|
||||
this.pluginApi.mute();
|
||||
} else {
|
||||
this.pluginApi.unMute();
|
||||
}
|
||||
this.muted = muted;
|
||||
this.dispatchEvent('volumechange');
|
||||
} else {
|
||||
this.pluginApi.setMuted(muted);
|
||||
}
|
||||
this.muted = muted;
|
||||
}
|
||||
},
|
||||
|
||||
// additional non-HTML5 methods
|
||||
setVideoSize: function (width, height) {
|
||||
|
||||
//if (this.pluginType == 'flash' || this.pluginType == 'silverlight') {
|
||||
if ( this.pluginElement.style) {
|
||||
this.pluginElement.style.width = width + 'px';
|
||||
this.pluginElement.style.height = height + 'px';
|
||||
}
|
||||
if (this.pluginApi != null && this.pluginApi.setVideoSize) {
|
||||
this.pluginApi.setVideoSize(width, height);
|
||||
}
|
||||
//}
|
||||
},
|
||||
|
||||
setFullscreen: function (fullscreen) {
|
||||
if (this.pluginApi != null && this.pluginApi.setFullscreen) {
|
||||
this.pluginApi.setFullscreen(fullscreen);
|
||||
}
|
||||
},
|
||||
|
||||
enterFullScreen: function() {
|
||||
if (this.pluginApi != null && this.pluginApi.setFullscreen) {
|
||||
this.setFullscreen(true);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
exitFullScreen: function() {
|
||||
if (this.pluginApi != null && this.pluginApi.setFullscreen) {
|
||||
this.setFullscreen(false);
|
||||
}
|
||||
},
|
||||
|
||||
// start: fake events
|
||||
addEventListener: function (eventName, callback, bubble) {
|
||||
this.events[eventName] = this.events[eventName] || [];
|
||||
this.events[eventName].push(callback);
|
||||
},
|
||||
removeEventListener: function (eventName, callback) {
|
||||
if (!eventName) { this.events = {}; return true; }
|
||||
var callbacks = this.events[eventName];
|
||||
if (!callbacks) return true;
|
||||
if (!callback) { this.events[eventName] = []; return true; }
|
||||
for (i = 0; i < callbacks.length; i++) {
|
||||
if (callbacks[i] === callback) {
|
||||
this.events[eventName].splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
dispatchEvent: function (eventName) {
|
||||
var i,
|
||||
args,
|
||||
callbacks = this.events[eventName];
|
||||
|
||||
if (callbacks) {
|
||||
args = Array.prototype.slice.call(arguments, 1);
|
||||
for (i = 0; i < callbacks.length; i++) {
|
||||
callbacks[i].apply(null, args);
|
||||
}
|
||||
}
|
||||
},
|
||||
// end: fake events
|
||||
|
||||
// fake DOM attribute methods
|
||||
hasAttribute: function(name){
|
||||
return (name in this.attributes);
|
||||
},
|
||||
removeAttribute: function(name){
|
||||
delete this.attributes[name];
|
||||
},
|
||||
getAttribute: function(name){
|
||||
if (this.hasAttribute(name)) {
|
||||
return this.attributes[name];
|
||||
}
|
||||
return '';
|
||||
},
|
||||
setAttribute: function(name, value){
|
||||
this.attributes[name] = value;
|
||||
},
|
||||
|
||||
remove: function() {
|
||||
mejs.Utility.removeSwf(this.pluginElement.id);
|
||||
mejs.MediaPluginBridge.unregisterPluginElement(this.pluginElement.id);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
// Namespace
|
||||
var mejs = mejs || {};
|
||||
|
||||
// version number
|
||||
mejs.version = '2.13.2';
|
||||
console.log('ME.js version', mejs.version);
|
||||
|
||||
// player number (for missing, same id attr)
|
||||
mejs.meIndex = 0;
|
||||
|
||||
// media types accepted by plugins
|
||||
mejs.plugins = {
|
||||
silverlight: [
|
||||
{version: [3,0], types: ['video/mp4','video/m4v','video/mov','video/wmv','audio/wma','audio/m4a','audio/mp3','audio/wav','audio/mpeg']}
|
||||
],
|
||||
flash: [
|
||||
{version: [9,0,124], types: ['video/mp4','video/m4v','video/mov','video/flv','video/rtmp','video/x-flv','audio/flv','audio/x-flv','audio/mp3','audio/m4a','audio/mpeg', 'video/youtube', 'video/x-youtube']}
|
||||
//,{version: [12,0], types: ['video/webm']} // for future reference (hopefully!)
|
||||
],
|
||||
youtube: [
|
||||
{version: null, types: ['video/youtube', 'video/x-youtube', 'audio/youtube', 'audio/x-youtube']}
|
||||
],
|
||||
vimeo: [
|
||||
{version: null, types: ['video/vimeo', 'video/x-vimeo']}
|
||||
]
|
||||
};
|
||||
@@ -0,0 +1,102 @@
|
||||
|
||||
// Core detector, plugins are added below
|
||||
mejs.PluginDetector = {
|
||||
|
||||
// main public function to test a plug version number PluginDetector.hasPluginVersion('flash',[9,0,125]);
|
||||
hasPluginVersion: function(plugin, v) {
|
||||
var pv = this.plugins[plugin];
|
||||
v[1] = v[1] || 0;
|
||||
v[2] = v[2] || 0;
|
||||
return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
|
||||
},
|
||||
|
||||
// cached values
|
||||
nav: window.navigator,
|
||||
ua: window.navigator.userAgent.toLowerCase(),
|
||||
|
||||
// stored version numbers
|
||||
plugins: [],
|
||||
|
||||
// runs detectPlugin() and stores the version number
|
||||
addPlugin: function(p, pluginName, mimeType, activeX, axDetect) {
|
||||
this.plugins[p] = this.detectPlugin(pluginName, mimeType, activeX, axDetect);
|
||||
},
|
||||
|
||||
// get the version number from the mimetype (all but IE) or ActiveX (IE)
|
||||
detectPlugin: function(pluginName, mimeType, activeX, axDetect) {
|
||||
|
||||
var version = [0,0,0],
|
||||
description,
|
||||
i,
|
||||
ax;
|
||||
|
||||
// Firefox, Webkit, Opera
|
||||
if (typeof(this.nav.plugins) != 'undefined' && typeof this.nav.plugins[pluginName] == 'object') {
|
||||
description = this.nav.plugins[pluginName].description;
|
||||
if (description && !(typeof this.nav.mimeTypes != 'undefined' && this.nav.mimeTypes[mimeType] && !this.nav.mimeTypes[mimeType].enabledPlugin)) {
|
||||
version = description.replace(pluginName, '').replace(/^\s+/,'').replace(/\sr/gi,'.').split('.');
|
||||
for (i=0; i<version.length; i++) {
|
||||
version[i] = parseInt(version[i].match(/\d+/), 10);
|
||||
}
|
||||
}
|
||||
// Internet Explorer / ActiveX
|
||||
} else if (typeof(window.ActiveXObject) != 'undefined') {
|
||||
try {
|
||||
ax = new ActiveXObject(activeX);
|
||||
if (ax) {
|
||||
version = axDetect(ax);
|
||||
}
|
||||
}
|
||||
catch (e) { }
|
||||
}
|
||||
return version;
|
||||
}
|
||||
};
|
||||
|
||||
// Add Flash detection
|
||||
mejs.PluginDetector.addPlugin('flash','Shockwave Flash','application/x-shockwave-flash','ShockwaveFlash.ShockwaveFlash', function(ax) {
|
||||
// adapted from SWFObject
|
||||
var version = [],
|
||||
d = ax.GetVariable("$version");
|
||||
if (d) {
|
||||
d = d.split(" ")[1].split(",");
|
||||
version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
|
||||
}
|
||||
return version;
|
||||
});
|
||||
|
||||
// Add Silverlight detection
|
||||
mejs.PluginDetector.addPlugin('silverlight','Silverlight Plug-In','application/x-silverlight-2','AgControl.AgControl', function (ax) {
|
||||
// Silverlight cannot report its version number to IE
|
||||
// but it does have a isVersionSupported function, so we have to loop through it to get a version number.
|
||||
// adapted from http://www.silverlightversion.com/
|
||||
var v = [0,0,0,0],
|
||||
loopMatch = function(ax, v, i, n) {
|
||||
while(ax.isVersionSupported(v[0]+ "."+ v[1] + "." + v[2] + "." + v[3])){
|
||||
v[i]+=n;
|
||||
}
|
||||
v[i] -= n;
|
||||
};
|
||||
loopMatch(ax, v, 0, 1);
|
||||
loopMatch(ax, v, 1, 1);
|
||||
loopMatch(ax, v, 2, 10000); // the third place in the version number is usually 5 digits (4.0.xxxxx)
|
||||
loopMatch(ax, v, 2, 1000);
|
||||
loopMatch(ax, v, 2, 100);
|
||||
loopMatch(ax, v, 2, 10);
|
||||
loopMatch(ax, v, 2, 1);
|
||||
loopMatch(ax, v, 3, 1);
|
||||
|
||||
return v;
|
||||
});
|
||||
// add adobe acrobat
|
||||
/*
|
||||
PluginDetector.addPlugin('acrobat','Adobe Acrobat','application/pdf','AcroPDF.PDF', function (ax) {
|
||||
var version = [],
|
||||
d = ax.GetVersions().split(',')[0].split('=')[1].split('.');
|
||||
|
||||
if (d) {
|
||||
version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
|
||||
}
|
||||
return version;
|
||||
});
|
||||
*/
|
||||
@@ -0,0 +1,906 @@
|
||||
// Handles calls from Flash/Silverlight and reports them as native <video/audio> events and properties
|
||||
mejs.MediaPluginBridge = {
|
||||
|
||||
pluginMediaElements:{},
|
||||
htmlMediaElements:{},
|
||||
|
||||
registerPluginElement: function (id, pluginMediaElement, htmlMediaElement) {
|
||||
this.pluginMediaElements[id] = pluginMediaElement;
|
||||
this.htmlMediaElements[id] = htmlMediaElement;
|
||||
},
|
||||
|
||||
unregisterPluginElement: function (id) {
|
||||
delete this.pluginMediaElements[id];
|
||||
delete this.htmlMediaElements[id];
|
||||
},
|
||||
|
||||
// when Flash/Silverlight is ready, it calls out to this method
|
||||
initPlugin: function (id) {
|
||||
|
||||
var pluginMediaElement = this.pluginMediaElements[id],
|
||||
htmlMediaElement = this.htmlMediaElements[id];
|
||||
|
||||
if (pluginMediaElement) {
|
||||
// find the javascript bridge
|
||||
switch (pluginMediaElement.pluginType) {
|
||||
case "flash":
|
||||
pluginMediaElement.pluginElement = pluginMediaElement.pluginApi = document.getElementById(id);
|
||||
break;
|
||||
case "silverlight":
|
||||
pluginMediaElement.pluginElement = document.getElementById(pluginMediaElement.id);
|
||||
pluginMediaElement.pluginApi = pluginMediaElement.pluginElement.Content.MediaElementJS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pluginMediaElement.pluginApi != null && pluginMediaElement.success) {
|
||||
pluginMediaElement.success(pluginMediaElement, htmlMediaElement);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// receives events from Flash/Silverlight and sends them out as HTML5 media events
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
|
||||
fireEvent: function (id, eventName, values) {
|
||||
|
||||
var
|
||||
e,
|
||||
i,
|
||||
bufferedTime,
|
||||
pluginMediaElement = this.pluginMediaElements[id];
|
||||
|
||||
if(!pluginMediaElement){
|
||||
return;
|
||||
}
|
||||
|
||||
// fake event object to mimic real HTML media event.
|
||||
e = {
|
||||
type: eventName,
|
||||
target: pluginMediaElement
|
||||
};
|
||||
|
||||
// attach all values to element and event object
|
||||
for (i in values) {
|
||||
pluginMediaElement[i] = values[i];
|
||||
e[i] = values[i];
|
||||
}
|
||||
|
||||
// fake the newer W3C buffered TimeRange (loaded and total have been removed)
|
||||
bufferedTime = values.bufferedTime || 0;
|
||||
|
||||
e.target.buffered = e.buffered = {
|
||||
start: function(index) {
|
||||
return 0;
|
||||
},
|
||||
end: function (index) {
|
||||
return bufferedTime;
|
||||
},
|
||||
length: 1
|
||||
};
|
||||
|
||||
pluginMediaElement.dispatchEvent(e.type, e);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Default options
|
||||
*/
|
||||
mejs.MediaElementDefaults = {
|
||||
// allows testing on HTML5, flash, silverlight
|
||||
// auto: attempts to detect what the browser can do
|
||||
// auto_plugin: prefer plugins and then attempt native HTML5
|
||||
// native: forces HTML5 playback
|
||||
// shim: disallows HTML5, will attempt either Flash or Silverlight
|
||||
// none: forces fallback view
|
||||
mode: 'auto',
|
||||
// remove or reorder to change plugin priority and availability
|
||||
plugins: ['flash','silverlight','youtube','vimeo'],
|
||||
// shows debug errors on screen
|
||||
enablePluginDebug: false,
|
||||
// use plugin for browsers that have trouble with Basic Authentication on HTTPS sites
|
||||
httpsBasicAuthSite: false,
|
||||
// overrides the type specified, useful for dynamic instantiation
|
||||
type: '',
|
||||
// path to Flash and Silverlight plugins
|
||||
pluginPath: mejs.Utility.getScriptPath(['mediaelement.js','mediaelement.min.js','mediaelement-and-player.js','mediaelement-and-player.min.js']),
|
||||
// name of flash file
|
||||
flashName: 'flashmediaelement.swf',
|
||||
// streamer for RTMP streaming
|
||||
flashStreamer: '',
|
||||
// turns on the smoothing filter in Flash
|
||||
enablePluginSmoothing: false,
|
||||
// enabled pseudo-streaming (seek) on .mp4 files
|
||||
enablePseudoStreaming: false,
|
||||
// start query parameter sent to server for pseudo-streaming
|
||||
pseudoStreamingStartQueryParam: 'start',
|
||||
// name of silverlight file
|
||||
silverlightName: 'silverlightmediaelement.xap',
|
||||
// default if the <video width> is not specified
|
||||
defaultVideoWidth: 480,
|
||||
// default if the <video height> is not specified
|
||||
defaultVideoHeight: 270,
|
||||
// overrides <video width>
|
||||
pluginWidth: -1,
|
||||
// overrides <video height>
|
||||
pluginHeight: -1,
|
||||
// additional plugin variables in 'key=value' form
|
||||
pluginVars: [],
|
||||
// rate in milliseconds for Flash and Silverlight to fire the timeupdate event
|
||||
// larger number is less accurate, but less strain on plugin->JavaScript bridge
|
||||
timerRate: 250,
|
||||
// initial volume for player
|
||||
startVolume: 0.8,
|
||||
success: function () { },
|
||||
error: function () { }
|
||||
};
|
||||
|
||||
/*
|
||||
Determines if a browser supports the <video> or <audio> element
|
||||
and returns either the native element or a Flash/Silverlight version that
|
||||
mimics HTML5 MediaElement
|
||||
*/
|
||||
mejs.MediaElement = function (el, o) {
|
||||
return mejs.HtmlMediaElementShim.create(el,o);
|
||||
};
|
||||
|
||||
mejs.HtmlMediaElementShim = {
|
||||
|
||||
create: function(el, o) {
|
||||
var
|
||||
options = mejs.MediaElementDefaults,
|
||||
htmlMediaElement = (typeof(el) == 'string') ? document.getElementById(el) : el,
|
||||
tagName = htmlMediaElement.tagName.toLowerCase(),
|
||||
isMediaTag = (tagName === 'audio' || tagName === 'video'),
|
||||
src = (isMediaTag) ? htmlMediaElement.getAttribute('src') : htmlMediaElement.getAttribute('href'),
|
||||
poster = htmlMediaElement.getAttribute('poster'),
|
||||
autoplay = htmlMediaElement.getAttribute('autoplay'),
|
||||
preload = htmlMediaElement.getAttribute('preload'),
|
||||
controls = htmlMediaElement.getAttribute('controls'),
|
||||
playback,
|
||||
prop;
|
||||
|
||||
// extend options
|
||||
for (prop in o) {
|
||||
options[prop] = o[prop];
|
||||
}
|
||||
|
||||
// clean up attributes
|
||||
src = (typeof src == 'undefined' || src === null || src == '') ? null : src;
|
||||
poster = (typeof poster == 'undefined' || poster === null) ? '' : poster;
|
||||
preload = (typeof preload == 'undefined' || preload === null || preload === 'false') ? 'none' : preload;
|
||||
autoplay = !(typeof autoplay == 'undefined' || autoplay === null || autoplay === 'false');
|
||||
controls = !(typeof controls == 'undefined' || controls === null || controls === 'false');
|
||||
|
||||
// test for HTML5 and plugin capabilities
|
||||
playback = this.determinePlayback(htmlMediaElement, options, mejs.MediaFeatures.supportsMediaTag, isMediaTag, src);
|
||||
playback.url = (playback.url !== null) ? mejs.Utility.absolutizeUrl(playback.url) : '';
|
||||
|
||||
if (playback.method == 'native') {
|
||||
// second fix for android
|
||||
if (mejs.MediaFeatures.isBustedAndroid) {
|
||||
htmlMediaElement.src = playback.url;
|
||||
htmlMediaElement.addEventListener('click', function() {
|
||||
htmlMediaElement.play();
|
||||
}, false);
|
||||
}
|
||||
|
||||
// add methods to native HTMLMediaElement
|
||||
return this.updateNative(playback, options, autoplay, preload);
|
||||
} else if (playback.method !== '') {
|
||||
// create plugin to mimic HTMLMediaElement
|
||||
|
||||
return this.createPlugin( playback, options, poster, autoplay, preload, controls);
|
||||
} else {
|
||||
// boo, no HTML5, no Flash, no Silverlight.
|
||||
this.createErrorMessage( playback, options, poster );
|
||||
|
||||
return this;
|
||||
}
|
||||
},
|
||||
|
||||
determinePlayback: function(htmlMediaElement, options, supportsMediaTag, isMediaTag, src) {
|
||||
var
|
||||
mediaFiles = [],
|
||||
i,
|
||||
j,
|
||||
k,
|
||||
l,
|
||||
n,
|
||||
type,
|
||||
result = { method: '', url: '', htmlMediaElement: htmlMediaElement, isVideo: (htmlMediaElement.tagName.toLowerCase() != 'audio')},
|
||||
pluginName,
|
||||
pluginVersions,
|
||||
pluginInfo,
|
||||
dummy,
|
||||
media;
|
||||
|
||||
// STEP 1: Get URL and type from <video src> or <source src>
|
||||
|
||||
// supplied type overrides <video type> and <source type>
|
||||
if (typeof options.type != 'undefined' && options.type !== '') {
|
||||
|
||||
// accept either string or array of types
|
||||
if (typeof options.type == 'string') {
|
||||
mediaFiles.push({type:options.type, url:src});
|
||||
} else {
|
||||
|
||||
for (i=0; i<options.type.length; i++) {
|
||||
mediaFiles.push({type:options.type[i], url:src});
|
||||
}
|
||||
}
|
||||
|
||||
// test for src attribute first
|
||||
} else if (src !== null) {
|
||||
type = this.formatType(src, htmlMediaElement.getAttribute('type'));
|
||||
mediaFiles.push({type:type, url:src});
|
||||
|
||||
// then test for <source> elements
|
||||
} else {
|
||||
// test <source> types to see if they are usable
|
||||
for (i = 0; i < htmlMediaElement.childNodes.length; i++) {
|
||||
n = htmlMediaElement.childNodes[i];
|
||||
if (n.nodeType == 1 && n.tagName.toLowerCase() == 'source') {
|
||||
src = n.getAttribute('src');
|
||||
type = this.formatType(src, n.getAttribute('type'));
|
||||
media = n.getAttribute('media');
|
||||
|
||||
if (!media || !window.matchMedia || (window.matchMedia && window.matchMedia(media).matches)) {
|
||||
mediaFiles.push({type:type, url:src});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// in the case of dynamicly created players
|
||||
// check for audio types
|
||||
if (!isMediaTag && mediaFiles.length > 0 && mediaFiles[0].url !== null && this.getTypeFromFile(mediaFiles[0].url).indexOf('audio') > -1) {
|
||||
result.isVideo = false;
|
||||
}
|
||||
|
||||
|
||||
// STEP 2: Test for playback method
|
||||
|
||||
// special case for Android which sadly doesn't implement the canPlayType function (always returns '')
|
||||
if (mejs.MediaFeatures.isBustedAndroid) {
|
||||
htmlMediaElement.canPlayType = function(type) {
|
||||
return (type.match(/video\/(mp4|m4v)/gi) !== null) ? 'maybe' : '';
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// test for native playback first
|
||||
if (supportsMediaTag && (options.mode === 'auto' || options.mode === 'auto_plugin' || options.mode === 'native') && !(mejs.MediaFeatures.isBustedNativeHTTPS && options.httpsBasicAuthSite === true)) {
|
||||
|
||||
if (!isMediaTag) {
|
||||
|
||||
// create a real HTML5 Media Element
|
||||
dummy = document.createElement( result.isVideo ? 'video' : 'audio');
|
||||
htmlMediaElement.parentNode.insertBefore(dummy, htmlMediaElement);
|
||||
htmlMediaElement.style.display = 'none';
|
||||
|
||||
// use this one from now on
|
||||
result.htmlMediaElement = htmlMediaElement = dummy;
|
||||
}
|
||||
|
||||
for (i=0; i<mediaFiles.length; i++) {
|
||||
// normal check
|
||||
if (htmlMediaElement.canPlayType(mediaFiles[i].type).replace(/no/, '') !== ''
|
||||
// special case for Mac/Safari 5.0.3 which answers '' to canPlayType('audio/mp3') but 'maybe' to canPlayType('audio/mpeg')
|
||||
|| htmlMediaElement.canPlayType(mediaFiles[i].type.replace(/mp3/,'mpeg')).replace(/no/, '') !== '') {
|
||||
result.method = 'native';
|
||||
result.url = mediaFiles[i].url;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.method === 'native') {
|
||||
if (result.url !== null) {
|
||||
htmlMediaElement.src = result.url;
|
||||
}
|
||||
|
||||
// if `auto_plugin` mode, then cache the native result but try plugins.
|
||||
if (options.mode !== 'auto_plugin') {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if native playback didn't work, then test plugins
|
||||
if (options.mode === 'auto' || options.mode === 'auto_plugin' || options.mode === 'shim') {
|
||||
for (i=0; i<mediaFiles.length; i++) {
|
||||
type = mediaFiles[i].type;
|
||||
|
||||
// test all plugins in order of preference [silverlight, flash]
|
||||
for (j=0; j<options.plugins.length; j++) {
|
||||
|
||||
pluginName = options.plugins[j];
|
||||
|
||||
// test version of plugin (for future features)
|
||||
pluginVersions = mejs.plugins[pluginName];
|
||||
|
||||
for (k=0; k<pluginVersions.length; k++) {
|
||||
pluginInfo = pluginVersions[k];
|
||||
|
||||
// test if user has the correct plugin version
|
||||
|
||||
// for youtube/vimeo
|
||||
if (pluginInfo.version == null ||
|
||||
|
||||
mejs.PluginDetector.hasPluginVersion(pluginName, pluginInfo.version)) {
|
||||
|
||||
// test for plugin playback types
|
||||
for (l=0; l<pluginInfo.types.length; l++) {
|
||||
// find plugin that can play the type
|
||||
if (type == pluginInfo.types[l]) {
|
||||
result.method = pluginName;
|
||||
result.url = mediaFiles[i].url;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// at this point, being in 'auto_plugin' mode implies that we tried plugins but failed.
|
||||
// if we have native support then return that.
|
||||
if (options.mode === 'auto_plugin' && result.method === 'native') {
|
||||
return result;
|
||||
}
|
||||
|
||||
// what if there's nothing to play? just grab the first available
|
||||
if (result.method === '' && mediaFiles.length > 0) {
|
||||
result.url = mediaFiles[0].url;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
formatType: function(url, type) {
|
||||
var ext;
|
||||
|
||||
// if no type is supplied, fake it with the extension
|
||||
if (url && !type) {
|
||||
return this.getTypeFromFile(url);
|
||||
} else {
|
||||
// only return the mime part of the type in case the attribute contains the codec
|
||||
// see http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#the-source-element
|
||||
// `video/mp4; codecs="avc1.42E01E, mp4a.40.2"` becomes `video/mp4`
|
||||
|
||||
if (type && ~type.indexOf(';')) {
|
||||
return type.substr(0, type.indexOf(';'));
|
||||
} else {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getTypeFromFile: function(url) {
|
||||
url = url.split('?')[0];
|
||||
var ext = url.substring(url.lastIndexOf('.') + 1).toLowerCase();
|
||||
return (/(mp4|m4v|ogg|ogv|webm|webmv|flv|wmv|mpeg|mov)/gi.test(ext) ? 'video' : 'audio') + '/' + this.getTypeFromExtension(ext);
|
||||
},
|
||||
|
||||
getTypeFromExtension: function(ext) {
|
||||
|
||||
switch (ext) {
|
||||
case 'mp4':
|
||||
case 'm4v':
|
||||
return 'mp4';
|
||||
case 'webm':
|
||||
case 'webma':
|
||||
case 'webmv':
|
||||
return 'webm';
|
||||
case 'ogg':
|
||||
case 'oga':
|
||||
case 'ogv':
|
||||
return 'ogg';
|
||||
default:
|
||||
return ext;
|
||||
}
|
||||
},
|
||||
|
||||
createErrorMessage: function(playback, options, poster) {
|
||||
var
|
||||
htmlMediaElement = playback.htmlMediaElement,
|
||||
errorContainer = document.createElement('div');
|
||||
|
||||
errorContainer.className = 'me-cannotplay';
|
||||
|
||||
try {
|
||||
errorContainer.style.width = htmlMediaElement.width + 'px';
|
||||
errorContainer.style.height = htmlMediaElement.height + 'px';
|
||||
} catch (e) {}
|
||||
|
||||
if (options.customError) {
|
||||
errorContainer.innerHTML = options.customError;
|
||||
} else {
|
||||
errorContainer.innerHTML = (poster !== '') ?
|
||||
'<a href="' + playback.url + '"><img src="' + poster + '" width="100%" height="100%" /></a>' :
|
||||
'<a href="' + playback.url + '"><span>' + mejs.i18n.t('Download File') + '</span></a>';
|
||||
}
|
||||
|
||||
htmlMediaElement.parentNode.insertBefore(errorContainer, htmlMediaElement);
|
||||
htmlMediaElement.style.display = 'none';
|
||||
|
||||
options.error(htmlMediaElement);
|
||||
},
|
||||
|
||||
createPlugin:function(playback, options, poster, autoplay, preload, controls) {
|
||||
var
|
||||
htmlMediaElement = playback.htmlMediaElement,
|
||||
width = 1,
|
||||
height = 1,
|
||||
pluginid = 'me_' + playback.method + '_' + (mejs.meIndex++),
|
||||
pluginMediaElement = new mejs.PluginMediaElement(pluginid, playback.method, playback.url),
|
||||
container = document.createElement('div'),
|
||||
specialIEContainer,
|
||||
node,
|
||||
initVars;
|
||||
|
||||
// copy tagName from html media element
|
||||
pluginMediaElement.tagName = htmlMediaElement.tagName
|
||||
|
||||
// copy attributes from html media element to plugin media element
|
||||
for (var i = 0; i < htmlMediaElement.attributes.length; i++) {
|
||||
var attribute = htmlMediaElement.attributes[i];
|
||||
if (attribute.specified == true) {
|
||||
pluginMediaElement.setAttribute(attribute.name, attribute.value);
|
||||
}
|
||||
}
|
||||
|
||||
// check for placement inside a <p> tag (sometimes WYSIWYG editors do this)
|
||||
node = htmlMediaElement.parentNode;
|
||||
while (node !== null && node.tagName.toLowerCase() != 'body') {
|
||||
if (node.parentNode.tagName.toLowerCase() == 'p') {
|
||||
node.parentNode.parentNode.insertBefore(node, node.parentNode);
|
||||
break;
|
||||
}
|
||||
node = node.parentNode;
|
||||
}
|
||||
|
||||
if (playback.isVideo) {
|
||||
width = (options.pluginWidth > 0) ? options.pluginWidth : (options.videoWidth > 0) ? options.videoWidth : (htmlMediaElement.getAttribute('width') !== null) ? htmlMediaElement.getAttribute('width') : options.defaultVideoWidth;
|
||||
height = (options.pluginHeight > 0) ? options.pluginHeight : (options.videoHeight > 0) ? options.videoHeight : (htmlMediaElement.getAttribute('height') !== null) ? htmlMediaElement.getAttribute('height') : options.defaultVideoHeight;
|
||||
|
||||
// in case of '%' make sure it's encoded
|
||||
width = mejs.Utility.encodeUrl(width);
|
||||
height = mejs.Utility.encodeUrl(height);
|
||||
|
||||
} else {
|
||||
if (options.enablePluginDebug) {
|
||||
width = 320;
|
||||
height = 240;
|
||||
}
|
||||
}
|
||||
|
||||
// register plugin
|
||||
pluginMediaElement.success = options.success;
|
||||
mejs.MediaPluginBridge.registerPluginElement(pluginid, pluginMediaElement, htmlMediaElement);
|
||||
|
||||
// add container (must be added to DOM before inserting HTML for IE)
|
||||
container.className = 'me-plugin';
|
||||
container.id = pluginid + '_container';
|
||||
|
||||
if (playback.isVideo) {
|
||||
htmlMediaElement.parentNode.insertBefore(container, htmlMediaElement);
|
||||
} else {
|
||||
document.body.insertBefore(container, document.body.childNodes[0]);
|
||||
}
|
||||
|
||||
// flash/silverlight vars
|
||||
initVars = [
|
||||
'id=' + pluginid,
|
||||
'isvideo=' + ((playback.isVideo) ? "true" : "false"),
|
||||
'autoplay=' + ((autoplay) ? "true" : "false"),
|
||||
'preload=' + preload,
|
||||
'width=' + width,
|
||||
'startvolume=' + options.startVolume,
|
||||
'timerrate=' + options.timerRate,
|
||||
'flashstreamer=' + options.flashStreamer,
|
||||
'height=' + height,
|
||||
'pseudostreamstart=' + options.pseudoStreamingStartQueryParam];
|
||||
|
||||
if (playback.url !== null) {
|
||||
if (playback.method == 'flash') {
|
||||
initVars.push('file=' + mejs.Utility.encodeUrl(playback.url));
|
||||
} else {
|
||||
initVars.push('file=' + playback.url);
|
||||
}
|
||||
}
|
||||
if (options.enablePluginDebug) {
|
||||
initVars.push('debug=true');
|
||||
}
|
||||
if (options.enablePluginSmoothing) {
|
||||
initVars.push('smoothing=true');
|
||||
}
|
||||
if (options.enablePseudoStreaming) {
|
||||
initVars.push('pseudostreaming=true');
|
||||
}
|
||||
if (controls) {
|
||||
initVars.push('controls=true'); // shows controls in the plugin if desired
|
||||
}
|
||||
if (options.pluginVars) {
|
||||
initVars = initVars.concat(options.pluginVars);
|
||||
}
|
||||
|
||||
switch (playback.method) {
|
||||
case 'silverlight':
|
||||
container.innerHTML =
|
||||
'<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="' + pluginid + '" name="' + pluginid + '" width="' + width + '" height="' + height + '" class="mejs-shim">' +
|
||||
'<param name="initParams" value="' + initVars.join(',') + '" />' +
|
||||
'<param name="windowless" value="true" />' +
|
||||
'<param name="background" value="black" />' +
|
||||
'<param name="minRuntimeVersion" value="3.0.0.0" />' +
|
||||
'<param name="autoUpgrade" value="true" />' +
|
||||
'<param name="source" value="' + options.pluginPath + options.silverlightName + '" />' +
|
||||
'</object>';
|
||||
break;
|
||||
|
||||
case 'flash':
|
||||
|
||||
if (mejs.MediaFeatures.isIE) {
|
||||
specialIEContainer = document.createElement('div');
|
||||
container.appendChild(specialIEContainer);
|
||||
specialIEContainer.outerHTML =
|
||||
'<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
|
||||
'id="' + pluginid + '" width="' + width + '" height="' + height + '" class="mejs-shim">' +
|
||||
'<param name="movie" value="' + options.pluginPath + options.flashName + '?x=' + (new Date()) + '" />' +
|
||||
'<param name="flashvars" value="' + initVars.join('&') + '" />' +
|
||||
'<param name="quality" value="high" />' +
|
||||
'<param name="bgcolor" value="#000000" />' +
|
||||
'<param name="wmode" value="transparent" />' +
|
||||
'<param name="allowScriptAccess" value="always" />' +
|
||||
'<param name="allowFullScreen" value="true" />' +
|
||||
'<param name="scale" value="default" />' +
|
||||
'</object>';
|
||||
|
||||
} else {
|
||||
|
||||
container.innerHTML =
|
||||
'<embed id="' + pluginid + '" name="' + pluginid + '" ' +
|
||||
'play="true" ' +
|
||||
'loop="false" ' +
|
||||
'quality="high" ' +
|
||||
'bgcolor="#000000" ' +
|
||||
'wmode="transparent" ' +
|
||||
'allowScriptAccess="always" ' +
|
||||
'allowFullScreen="true" ' +
|
||||
'type="application/x-shockwave-flash" pluginspage="//www.macromedia.com/go/getflashplayer" ' +
|
||||
'src="' + options.pluginPath + options.flashName + '" ' +
|
||||
'flashvars="' + initVars.join('&') + '" ' +
|
||||
'width="' + width + '" ' +
|
||||
'height="' + height + '" ' +
|
||||
'scale="default"' +
|
||||
'class="mejs-shim"></embed>';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'youtube':
|
||||
|
||||
|
||||
var
|
||||
videoId = playback.url.substr(playback.url.lastIndexOf('=')+1);
|
||||
youtubeSettings = {
|
||||
container: container,
|
||||
containerId: container.id,
|
||||
pluginMediaElement: pluginMediaElement,
|
||||
pluginId: pluginid,
|
||||
videoId: videoId,
|
||||
height: height,
|
||||
width: width
|
||||
};
|
||||
|
||||
if (mejs.PluginDetector.hasPluginVersion('flash', [10,0,0]) ) {
|
||||
mejs.YouTubeApi.createFlash(youtubeSettings);
|
||||
} else {
|
||||
mejs.YouTubeApi.enqueueIframe(youtubeSettings);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// DEMO Code. Does NOT work.
|
||||
case 'vimeo':
|
||||
//console.log('vimeoid');
|
||||
|
||||
pluginMediaElement.vimeoid = playback.url.substr(playback.url.lastIndexOf('/')+1);
|
||||
|
||||
container.innerHTML ='<iframe src="http://player.vimeo.com/video/' + pluginMediaElement.vimeoid + '?portrait=0&byline=0&title=0" width="' + width +'" height="' + height +'" frameborder="0" class="mejs-shim"></iframe>';
|
||||
|
||||
/*
|
||||
container.innerHTML =
|
||||
'<object width="' + width + '" height="' + height + '" class="mejs-shim">' +
|
||||
'<param name="allowfullscreen" value="true" />' +
|
||||
'<param name="allowscriptaccess" value="always" />' +
|
||||
'<param name="flashvars" value="api=1" />' +
|
||||
'<param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=' + pluginMediaElement.vimeoid + '&server=vimeo.com&show_title=0&show_byline=0&show_portrait=0&color=00adef&fullscreen=1&autoplay=0&loop=0" />' +
|
||||
'<embed src="//vimeo.com/moogaloop.swf?api=1&clip_id=' + pluginMediaElement.vimeoid + '&server=vimeo.com&show_title=0&show_byline=0&show_portrait=0&color=00adef&fullscreen=1&autoplay=0&loop=0" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="' + width + '" height="' + height + '" class="mejs-shim"></embed>' +
|
||||
'</object>';
|
||||
*/
|
||||
|
||||
break;
|
||||
}
|
||||
// hide original element
|
||||
htmlMediaElement.style.display = 'none';
|
||||
// prevent browser from autoplaying when using a plugin
|
||||
htmlMediaElement.removeAttribute('autoplay');
|
||||
|
||||
// FYI: options.success will be fired by the MediaPluginBridge
|
||||
|
||||
return pluginMediaElement;
|
||||
},
|
||||
|
||||
updateNative: function(playback, options, autoplay, preload) {
|
||||
|
||||
var htmlMediaElement = playback.htmlMediaElement,
|
||||
m;
|
||||
|
||||
|
||||
// add methods to video object to bring it into parity with Flash Object
|
||||
for (m in mejs.HtmlMediaElement) {
|
||||
htmlMediaElement[m] = mejs.HtmlMediaElement[m];
|
||||
}
|
||||
|
||||
/*
|
||||
Chrome now supports preload="none"
|
||||
if (mejs.MediaFeatures.isChrome) {
|
||||
|
||||
// special case to enforce preload attribute (Chrome doesn't respect this)
|
||||
if (preload === 'none' && !autoplay) {
|
||||
|
||||
// forces the browser to stop loading (note: fails in IE9)
|
||||
htmlMediaElement.src = '';
|
||||
htmlMediaElement.load();
|
||||
htmlMediaElement.canceledPreload = true;
|
||||
|
||||
htmlMediaElement.addEventListener('play',function() {
|
||||
if (htmlMediaElement.canceledPreload) {
|
||||
htmlMediaElement.src = playback.url;
|
||||
htmlMediaElement.load();
|
||||
htmlMediaElement.play();
|
||||
htmlMediaElement.canceledPreload = false;
|
||||
}
|
||||
}, false);
|
||||
// for some reason Chrome forgets how to autoplay sometimes.
|
||||
} else if (autoplay) {
|
||||
htmlMediaElement.load();
|
||||
htmlMediaElement.play();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// fire success code
|
||||
options.success(htmlMediaElement, htmlMediaElement);
|
||||
|
||||
return htmlMediaElement;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
- test on IE (object vs. embed)
|
||||
- determine when to use iframe (Firefox, Safari, Mobile) vs. Flash (Chrome, IE)
|
||||
- fullscreen?
|
||||
*/
|
||||
|
||||
// YouTube Flash and Iframe API
|
||||
mejs.YouTubeApi = {
|
||||
isIframeStarted: false,
|
||||
isIframeLoaded: false,
|
||||
loadIframeApi: function() {
|
||||
if (!this.isIframeStarted) {
|
||||
var tag = document.createElement('script');
|
||||
tag.src = "//www.youtube.com/player_api";
|
||||
var firstScriptTag = document.getElementsByTagName('script')[0];
|
||||
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
||||
this.isIframeStarted = true;
|
||||
}
|
||||
},
|
||||
iframeQueue: [],
|
||||
enqueueIframe: function(yt) {
|
||||
|
||||
if (this.isLoaded) {
|
||||
this.createIframe(yt);
|
||||
} else {
|
||||
this.loadIframeApi();
|
||||
this.iframeQueue.push(yt);
|
||||
}
|
||||
},
|
||||
createIframe: function(settings) {
|
||||
|
||||
var
|
||||
pluginMediaElement = settings.pluginMediaElement,
|
||||
player = new YT.Player(settings.containerId, {
|
||||
height: settings.height,
|
||||
width: settings.width,
|
||||
videoId: settings.videoId,
|
||||
playerVars: {controls:0},
|
||||
events: {
|
||||
'onReady': function() {
|
||||
|
||||
// hook up iframe object to MEjs
|
||||
settings.pluginMediaElement.pluginApi = player;
|
||||
|
||||
// init mejs
|
||||
mejs.MediaPluginBridge.initPlugin(settings.pluginId);
|
||||
|
||||
// create timer
|
||||
setInterval(function() {
|
||||
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate');
|
||||
}, 250);
|
||||
},
|
||||
'onStateChange': function(e) {
|
||||
|
||||
mejs.YouTubeApi.handleStateChange(e.data, player, pluginMediaElement);
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
createEvent: function (player, pluginMediaElement, eventName) {
|
||||
var obj = {
|
||||
type: eventName,
|
||||
target: pluginMediaElement
|
||||
};
|
||||
|
||||
if (player && player.getDuration) {
|
||||
|
||||
// time
|
||||
pluginMediaElement.currentTime = obj.currentTime = player.getCurrentTime();
|
||||
pluginMediaElement.duration = obj.duration = player.getDuration();
|
||||
|
||||
// state
|
||||
obj.paused = pluginMediaElement.paused;
|
||||
obj.ended = pluginMediaElement.ended;
|
||||
|
||||
// sound
|
||||
obj.muted = player.isMuted();
|
||||
obj.volume = player.getVolume() / 100;
|
||||
|
||||
// progress
|
||||
obj.bytesTotal = player.getVideoBytesTotal();
|
||||
obj.bufferedBytes = player.getVideoBytesLoaded();
|
||||
|
||||
// fake the W3C buffered TimeRange
|
||||
var bufferedTime = obj.bufferedBytes / obj.bytesTotal * obj.duration;
|
||||
|
||||
obj.target.buffered = obj.buffered = {
|
||||
start: function(index) {
|
||||
return 0;
|
||||
},
|
||||
end: function (index) {
|
||||
return bufferedTime;
|
||||
},
|
||||
length: 1
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// send event up the chain
|
||||
pluginMediaElement.dispatchEvent(obj.type, obj);
|
||||
},
|
||||
|
||||
iFrameReady: function() {
|
||||
|
||||
this.isLoaded = true;
|
||||
this.isIframeLoaded = true;
|
||||
|
||||
while (this.iframeQueue.length > 0) {
|
||||
var settings = this.iframeQueue.pop();
|
||||
this.createIframe(settings);
|
||||
}
|
||||
},
|
||||
|
||||
// FLASH!
|
||||
flashPlayers: {},
|
||||
createFlash: function(settings) {
|
||||
|
||||
this.flashPlayers[settings.pluginId] = settings;
|
||||
|
||||
/*
|
||||
settings.container.innerHTML =
|
||||
'<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="//www.youtube.com/apiplayer?enablejsapi=1&playerapiid=' + settings.pluginId + '&version=3&autoplay=0&controls=0&modestbranding=1&loop=0" ' +
|
||||
'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; " class="mejs-shim">' +
|
||||
'<param name="allowScriptAccess" value="always">' +
|
||||
'<param name="wmode" value="transparent">' +
|
||||
'</object>';
|
||||
*/
|
||||
|
||||
var specialIEContainer,
|
||||
youtubeUrl = '//www.youtube.com/apiplayer?enablejsapi=1&playerapiid=' + settings.pluginId + '&version=3&autoplay=0&controls=0&modestbranding=1&loop=0';
|
||||
|
||||
if (mejs.MediaFeatures.isIE) {
|
||||
|
||||
specialIEContainer = document.createElement('div');
|
||||
settings.container.appendChild(specialIEContainer);
|
||||
specialIEContainer.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
|
||||
'id="' + settings.pluginId + '" width="' + settings.width + '" height="' + settings.height + '" class="mejs-shim">' +
|
||||
'<param name="movie" value="' + youtubeUrl + '" />' +
|
||||
'<param name="wmode" value="transparent" />' +
|
||||
'<param name="allowScriptAccess" value="always" />' +
|
||||
'<param name="allowFullScreen" value="true" />' +
|
||||
'</object>';
|
||||
} else {
|
||||
settings.container.innerHTML =
|
||||
'<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="' + youtubeUrl + '" ' +
|
||||
'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; " class="mejs-shim">' +
|
||||
'<param name="allowScriptAccess" value="always">' +
|
||||
'<param name="wmode" value="transparent">' +
|
||||
'</object>';
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
flashReady: function(id) {
|
||||
var
|
||||
settings = this.flashPlayers[id],
|
||||
player = document.getElementById(id),
|
||||
pluginMediaElement = settings.pluginMediaElement;
|
||||
|
||||
// hook up and return to MediaELementPlayer.success
|
||||
pluginMediaElement.pluginApi =
|
||||
pluginMediaElement.pluginElement = player;
|
||||
mejs.MediaPluginBridge.initPlugin(id);
|
||||
|
||||
// load the youtube video
|
||||
player.cueVideoById(settings.videoId);
|
||||
|
||||
var callbackName = settings.containerId + '_callback';
|
||||
|
||||
window[callbackName] = function(e) {
|
||||
mejs.YouTubeApi.handleStateChange(e, player, pluginMediaElement);
|
||||
}
|
||||
|
||||
player.addEventListener('onStateChange', callbackName);
|
||||
|
||||
setInterval(function() {
|
||||
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate');
|
||||
}, 250);
|
||||
},
|
||||
|
||||
handleStateChange: function(youTubeState, player, pluginMediaElement) {
|
||||
switch (youTubeState) {
|
||||
case -1: // not started
|
||||
pluginMediaElement.paused = true;
|
||||
pluginMediaElement.ended = true;
|
||||
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'loadedmetadata');
|
||||
//createYouTubeEvent(player, pluginMediaElement, 'loadeddata');
|
||||
break;
|
||||
case 0:
|
||||
pluginMediaElement.paused = false;
|
||||
pluginMediaElement.ended = true;
|
||||
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'ended');
|
||||
break;
|
||||
case 1:
|
||||
pluginMediaElement.paused = false;
|
||||
pluginMediaElement.ended = false;
|
||||
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'play');
|
||||
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'playing');
|
||||
break;
|
||||
case 2:
|
||||
pluginMediaElement.paused = true;
|
||||
pluginMediaElement.ended = false;
|
||||
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'pause');
|
||||
break;
|
||||
case 3: // buffering
|
||||
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'progress');
|
||||
break;
|
||||
case 5:
|
||||
// cued?
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// IFRAME
|
||||
function onYouTubePlayerAPIReady() {
|
||||
mejs.YouTubeApi.iFrameReady();
|
||||
}
|
||||
// FLASH
|
||||
function onYouTubePlayerReady(id) {
|
||||
mejs.YouTubeApi.flashReady(id);
|
||||
}
|
||||
|
||||
window.mejs = mejs;
|
||||
window.MediaElement = mejs.MediaElement;
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
Utility methods
|
||||
*/
|
||||
mejs.Utility = {
|
||||
encodeUrl: function(url) {
|
||||
return encodeURIComponent(url); //.replace(/\?/gi,'%3F').replace(/=/gi,'%3D').replace(/&/gi,'%26');
|
||||
},
|
||||
escapeHTML: function(s) {
|
||||
return s.toString().split('&').join('&').split('<').join('<').split('"').join('"');
|
||||
},
|
||||
absolutizeUrl: function(url) {
|
||||
var el = document.createElement('div');
|
||||
el.innerHTML = '<a href="' + this.escapeHTML(url) + '">x</a>';
|
||||
return el.firstChild.href;
|
||||
},
|
||||
getScriptPath: function(scriptNames) {
|
||||
var
|
||||
i = 0,
|
||||
j,
|
||||
codePath = '',
|
||||
testname = '',
|
||||
slashPos,
|
||||
filenamePos,
|
||||
scriptUrl,
|
||||
scriptPath,
|
||||
scriptFilename,
|
||||
scripts = document.getElementsByTagName('script'),
|
||||
il = scripts.length,
|
||||
jl = scriptNames.length;
|
||||
|
||||
// go through all <script> tags
|
||||
for (; i < il; i++) {
|
||||
scriptUrl = scripts[i].src;
|
||||
slashPos = scriptUrl.lastIndexOf('/');
|
||||
if (slashPos > -1) {
|
||||
scriptFilename = scriptUrl.substring(slashPos + 1);
|
||||
scriptPath = scriptUrl.substring(0, slashPos + 1);
|
||||
} else {
|
||||
scriptFilename = scriptUrl;
|
||||
scriptPath = '';
|
||||
}
|
||||
|
||||
// see if any <script> tags have a file name that matches the
|
||||
for (j = 0; j < jl; j++) {
|
||||
testname = scriptNames[j];
|
||||
filenamePos = scriptFilename.indexOf(testname);
|
||||
if (filenamePos > -1) {
|
||||
codePath = scriptPath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if we found a path, then break and return it
|
||||
if (codePath !== '') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// send the best path back
|
||||
return codePath;
|
||||
},
|
||||
secondsToTimeCode: function(time, forceHours, showFrameCount, fps) {
|
||||
//add framecount
|
||||
if (typeof showFrameCount == 'undefined') {
|
||||
showFrameCount=false;
|
||||
} else if(typeof fps == 'undefined') {
|
||||
fps = 25;
|
||||
}
|
||||
|
||||
var hours = Math.floor(time / 3600) % 24,
|
||||
minutes = Math.floor(time / 60) % 60,
|
||||
seconds = Math.floor(time % 60),
|
||||
frames = Math.floor(((time % 1)*fps).toFixed(3)),
|
||||
result =
|
||||
( (forceHours || hours > 0) ? (hours < 10 ? '0' + hours : hours) + ':' : '')
|
||||
+ (minutes < 10 ? '0' + minutes : minutes) + ':'
|
||||
+ (seconds < 10 ? '0' + seconds : seconds)
|
||||
+ ((showFrameCount) ? ':' + (frames < 10 ? '0' + frames : frames) : '');
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
timeCodeToSeconds: function(hh_mm_ss_ff, forceHours, showFrameCount, fps){
|
||||
if (typeof showFrameCount == 'undefined') {
|
||||
showFrameCount=false;
|
||||
} else if(typeof fps == 'undefined') {
|
||||
fps = 25;
|
||||
}
|
||||
|
||||
var tc_array = hh_mm_ss_ff.split(":"),
|
||||
tc_hh = parseInt(tc_array[0], 10),
|
||||
tc_mm = parseInt(tc_array[1], 10),
|
||||
tc_ss = parseInt(tc_array[2], 10),
|
||||
tc_ff = 0,
|
||||
tc_in_seconds = 0;
|
||||
|
||||
if (showFrameCount) {
|
||||
tc_ff = parseInt(tc_array[3])/fps;
|
||||
}
|
||||
|
||||
tc_in_seconds = ( tc_hh * 3600 ) + ( tc_mm * 60 ) + tc_ss + tc_ff;
|
||||
|
||||
return tc_in_seconds;
|
||||
},
|
||||
|
||||
|
||||
convertSMPTEtoSeconds: function (SMPTE) {
|
||||
if (typeof SMPTE != 'string')
|
||||
return false;
|
||||
|
||||
SMPTE = SMPTE.replace(',', '.');
|
||||
|
||||
var secs = 0,
|
||||
decimalLen = (SMPTE.indexOf('.') != -1) ? SMPTE.split('.')[1].length : 0,
|
||||
multiplier = 1;
|
||||
|
||||
SMPTE = SMPTE.split(':').reverse();
|
||||
|
||||
for (var i = 0; i < SMPTE.length; i++) {
|
||||
multiplier = 1;
|
||||
if (i > 0) {
|
||||
multiplier = Math.pow(60, i);
|
||||
}
|
||||
secs += Number(SMPTE[i]) * multiplier;
|
||||
}
|
||||
return Number(secs.toFixed(decimalLen));
|
||||
},
|
||||
|
||||
/* borrowed from SWFObject: http://code.google.com/p/swfobject/source/browse/trunk/swfobject/src/swfobject.js#474 */
|
||||
removeSwf: function(id) {
|
||||
var obj = document.getElementById(id);
|
||||
if (obj && /object|embed/i.test(obj.nodeName)) {
|
||||
if (mejs.MediaFeatures.isIE) {
|
||||
obj.style.display = "none";
|
||||
(function(){
|
||||
if (obj.readyState == 4) {
|
||||
mejs.Utility.removeObjectInIE(id);
|
||||
} else {
|
||||
setTimeout(arguments.callee, 10);
|
||||
}
|
||||
})();
|
||||
} else {
|
||||
obj.parentNode.removeChild(obj);
|
||||
}
|
||||
}
|
||||
},
|
||||
removeObjectInIE: function(id) {
|
||||
var obj = document.getElementById(id);
|
||||
if (obj) {
|
||||
for (var i in obj) {
|
||||
if (typeof obj[i] == "function") {
|
||||
obj[i] = null;
|
||||
}
|
||||
}
|
||||
obj.parentNode.removeChild(obj);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,243 @@
|
||||
|
||||
// VAST ads plugin
|
||||
// Sponsored by Minoto Video
|
||||
|
||||
(function($) {
|
||||
|
||||
$.extend(mejs.MepDefaults, {
|
||||
// URL to vast data: 'http://minotovideo.com/sites/minotovideo.com/files/upload/eday_vast_tag.xml'
|
||||
vastAdTagUrl: ''
|
||||
});
|
||||
|
||||
$.extend(MediaElementPlayer.prototype, {
|
||||
buildvast: function(player, controls, layers, media) {
|
||||
|
||||
var t = this;
|
||||
|
||||
// begin loading
|
||||
if (t.options.vastAdTagUrl != '') {
|
||||
t.vastLoadAdTagInfo();
|
||||
}
|
||||
|
||||
// make sure the preroll ad system is ready (it will ensure it can't be called twice)
|
||||
t.buildads(player, controls, layers, media);
|
||||
|
||||
|
||||
t.vastSetupEvents();
|
||||
},
|
||||
|
||||
vastAdTagIsLoading: false,
|
||||
|
||||
vastAdTagIsLoaded: false,
|
||||
|
||||
vastStartedPlaying: false,
|
||||
|
||||
vastAdTags: [],
|
||||
|
||||
vastSetupEvents: function() {
|
||||
var t = this;
|
||||
|
||||
|
||||
// START: preroll
|
||||
t.container.on('mejsprerollstarted', function() {
|
||||
|
||||
console.log('VAST','mejsprerollstarted');
|
||||
|
||||
if (t.vastAdTags.length > 0) {
|
||||
|
||||
var adTag = t.vastAdTags[0];
|
||||
|
||||
// always fire this event
|
||||
if (adTag.trackingEvents['start']) {
|
||||
t.adsLoadUrl(adTag.trackingEvents['start']);
|
||||
}
|
||||
|
||||
// only do impressions once
|
||||
if (!adTag.shown && adTag.impressions.length > 0) {
|
||||
|
||||
for (var i=0, il=adTag.impressions.length; i<il; i++) {
|
||||
t.adsLoadUrl(adTag.impressions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
adTag.shown = true;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// END: preroll
|
||||
t.container.on('mejsprerollended', function() {
|
||||
|
||||
console.log('VAST','mejsprerollended');
|
||||
|
||||
if (t.vastAdTags.length > 0 && t.vastAdTags[0].trackingEvents['complete']) {
|
||||
t.adsLoadUrl(t.vastAdTags[0].trackingEvents['complete']);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
vastSetAdTagUrl: function(url) {
|
||||
|
||||
var t = this;
|
||||
|
||||
// set and reset
|
||||
t.options.vastAdTagUrl = url;
|
||||
t.vastAdTagIsLoaded = false;
|
||||
t.vastAdTags = [];
|
||||
},
|
||||
|
||||
vastLoadAdTagInfo: function() {
|
||||
console.log('loading vast ad data');
|
||||
|
||||
var t = this;
|
||||
|
||||
// set this to stop playback
|
||||
t.adsDataIsLoading = true;
|
||||
t.vastAdTagIsLoading = true;
|
||||
|
||||
// try straight load first
|
||||
t.loadAdTagInfoDirect();
|
||||
},
|
||||
|
||||
loadAdTagInfoDirect: function() {
|
||||
console.log('loading vast:direct');
|
||||
|
||||
var t= this;
|
||||
|
||||
$.ajax({
|
||||
url: t.options.vastAdTagUrl,
|
||||
crossDomain: true,
|
||||
success: function(data) {
|
||||
console.log('vast:direct:success', data);
|
||||
|
||||
t.vastParseVastData(data)
|
||||
},
|
||||
error: function(err) {
|
||||
console.log('vast:direct:error', err);
|
||||
|
||||
// fallback to Yahoo proxy
|
||||
t.loadAdTagInfoProxy();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
loadAdTagInfoProxy: function() {
|
||||
console.log('loading vast:proxy:yahoo');
|
||||
|
||||
var t = this,
|
||||
protocol = location.protocol,
|
||||
hostname = location.hostname,
|
||||
exRegex = RegExp(protocol + '//' + hostname),
|
||||
query = 'select * from xml where url="' + encodeURI(t.options.vastAdTagUrl) +'"',
|
||||
yahooUrl = 'http' + (/^https/.test(protocol)?'s':'') + '://query.yahooapis.com/v1/public/yql?format=xml&q=' + query;
|
||||
|
||||
|
||||
|
||||
$.ajax({
|
||||
url: yahooUrl,
|
||||
crossDomain: true,
|
||||
success: function(data) {
|
||||
console.log('vast:proxy:yahoo:success', data);
|
||||
|
||||
t.vastParseVastData(data);
|
||||
},
|
||||
error: function(err) {
|
||||
console.log('vast:proxy:yahoo:error', err);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
vastParseVastData: function(data) {
|
||||
|
||||
var t = this;
|
||||
|
||||
// clear out data
|
||||
t.vastAdTags = [];
|
||||
|
||||
$(data).find('Ad').each(function(index, node) {
|
||||
|
||||
var
|
||||
adNode = $(node),
|
||||
|
||||
adTag = {
|
||||
id: adNode.attr('id'),
|
||||
title: $.trim( adNode.find('AdTitle').text() ),
|
||||
description: $.trim( adNode.find('Description').text() ),
|
||||
impressions: [],
|
||||
clickThrough: $.trim( adNode.find('ClickThrough').text() ),
|
||||
mediaFiles: [],
|
||||
trackingEvents: {},
|
||||
|
||||
// internal tracking if it's been used
|
||||
shown: false
|
||||
};
|
||||
|
||||
t.vastAdTags.push(adTag);
|
||||
|
||||
|
||||
// parse all needed nodes
|
||||
adNode.find('Impression').each(function() {
|
||||
adTag.impressions.push( $.trim( $(this).text() ) );
|
||||
});
|
||||
|
||||
adNode.find('Tracking').each(function(index, node) {
|
||||
var trackingEvent = $(node);
|
||||
|
||||
adTag.trackingEvents[trackingEvent.attr('event')] = $.trim( trackingEvent.text() );
|
||||
|
||||
});
|
||||
|
||||
|
||||
adNode.find('MediaFile').each(function(index, node) {
|
||||
var mediaFile = $(node),
|
||||
type = mediaFile.attr('type');
|
||||
|
||||
if (t.media.canPlayType(type).toString().replace(/no/,'').replace(/false/,'') != '') {
|
||||
|
||||
adTag.mediaFiles.push({
|
||||
id: mediaFile.attr('id'),
|
||||
delivery: mediaFile.attr('delivery'),
|
||||
type: mediaFile.attr('type'),
|
||||
bitrate: mediaFile.attr('bitrate'),
|
||||
width: mediaFile.attr('width'),
|
||||
height: mediaFile.attr('height'),
|
||||
url: $.trim( mediaFile.text() )
|
||||
} );
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// DONE
|
||||
t.vastLoaded();
|
||||
},
|
||||
|
||||
vastLoaded: function() {
|
||||
var t = this;
|
||||
|
||||
t.vastAdTagIsLoaded = true;
|
||||
t.vastAdTagIsLoading = false;
|
||||
t.adsDataIsLoading = false;
|
||||
|
||||
t.vastStartPreroll();
|
||||
},
|
||||
|
||||
vastStartPreroll: function() {
|
||||
console.log('vastStartPreroll');
|
||||
|
||||
var t = this;
|
||||
|
||||
// if we have a media URL, then send it up to the ads plugin as a preroll
|
||||
if (t.vastAdTags.length > 0 && t.vastAdTags[0].mediaFiles.length > 0) {
|
||||
|
||||
t.options.adsPrerollMediaUrl = t.vastAdTags[0].mediaFiles[0].url;
|
||||
t.options.adsPrerollAdUrl = t.vastAdTags[0].clickThrough;
|
||||
t.adsStartPreroll();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})(mejs.$);
|
||||
@@ -0,0 +1,312 @@
|
||||
// VAST ads plugin
|
||||
// Sponsored by Minoto Video
|
||||
|
||||
// 2013/02/01 0.5 research
|
||||
// 2013/02/09 1.5 build loading mechanism
|
||||
// 2013/02/10 2.5 events to play preroll, skip function, start/end calls, \
|
||||
// 2013/02/11 2 click events
|
||||
// ----
|
||||
// 2013/02/23 3.5 split into a generic pre-roll plugin
|
||||
|
||||
|
||||
(function($) {
|
||||
|
||||
// on time insert into head
|
||||
$('head').append($('<style>' +
|
||||
'.mejs-ads a {' +
|
||||
' display: block; ' +
|
||||
' position: absolute;' +
|
||||
' right: 0;' +
|
||||
' top: 0;' +
|
||||
' width: 100%; ' +
|
||||
' height: 100%; ' +
|
||||
' display: block; ' +
|
||||
'}' +
|
||||
'.mejs-ads .mejs-ads-skip-block {' +
|
||||
' display: block; ' +
|
||||
' position: absolute;' +
|
||||
' right: 0;' +
|
||||
' top: 0;' +
|
||||
' padding: 10px; ' +
|
||||
' background: #000; ' +
|
||||
' background: rgba(0,0,0,0.5); ' +
|
||||
' color: #fff; ' +
|
||||
'}' +
|
||||
'.mejs-ads .mejs-ads-skip-button {' +
|
||||
' cursor: pointer; ' +
|
||||
'}' +
|
||||
'.mejs-ads .mejs-ads-skip-button:hover {' +
|
||||
' text-decoration: underline; ' +
|
||||
'}' +
|
||||
'</style>'));
|
||||
|
||||
|
||||
$.extend(mejs.MepDefaults, {
|
||||
// URL to a media file
|
||||
adsPrerollMediaUrl: '',
|
||||
|
||||
// URL for lcicking ad
|
||||
adsPrerollAdUrl: '',
|
||||
|
||||
// if true, allows user to skip the pre-roll ad
|
||||
adsPrerollAdEnableSkip: false,
|
||||
|
||||
// if adsPrerollAdEnableSkip=true and this is a positive number, it will only allow skipping after the time has elasped
|
||||
adsPrerollAdSkipSeconds: -1
|
||||
});
|
||||
|
||||
$.extend(MediaElementPlayer.prototype, {
|
||||
|
||||
// allows other plugins to all this one
|
||||
adsLoaded: false,
|
||||
|
||||
// prevents playback in until async ad data is ready (e.g. VAST)
|
||||
adsDataIsLoading: false,
|
||||
|
||||
// stores the main media URL when an ad is playing
|
||||
adsCurrentMediaUrl: '',
|
||||
adsCurrentMediaDuration: 0,
|
||||
|
||||
// true when the user clicks play for the first time, or if autoplay is set
|
||||
adsPlayerHasStarted: false,
|
||||
|
||||
buildads: function(player, controls, layers, media) {
|
||||
|
||||
var t = this;
|
||||
|
||||
if (t.adsLoaded) {
|
||||
return;
|
||||
} else {
|
||||
t.adsLoaded = true;
|
||||
}
|
||||
|
||||
// add layer for ad links and skipping
|
||||
player.adsLayer =
|
||||
$('<div class="mejs-layer mejs-overlay mejs-ads">' +
|
||||
'<a href="#" target="_blank"> </a>' +
|
||||
'<div class="mejs-ads-skip-block">' +
|
||||
'<span class="mejs-ads-skip-message"></span>' +
|
||||
'<span class="mejs-ads-skip-button">Skip Ad »</span>' +
|
||||
'</div>' +
|
||||
'</div>')
|
||||
.insertBefore( layers.find('.mejs-overlay-play') )
|
||||
.hide();
|
||||
|
||||
player.adsLayer.find('a')
|
||||
.on('click', $.proxy(t.adsAdClick, t) );
|
||||
|
||||
player.adsSkipBlock = player.adsLayer.find('.mejs-ads-skip-block').hide();
|
||||
player.adsSkipMessage = player.adsLayer.find('.mejs-ads-skip-message').hide();
|
||||
|
||||
player.adsSkipButton = player.adsLayer.find('.mejs-ads-skip-button')
|
||||
.on('click', $.proxy(t.adsSkipClick, t) );
|
||||
|
||||
|
||||
// create proxies (only needed for events we want to remove later)
|
||||
t.adsMediaTryingToStartProxy = $.proxy(t.adsMediaTryingToStart, t);
|
||||
t.adsPrerollStartedProxy = $.proxy(t.adsPrerollStarted, t);
|
||||
t.adsPrerollMetaProxy = $.proxy(t.adsPrerollMeta, t);
|
||||
t.adsPrerollUpdateProxy = $.proxy(t.adsPrerollUpdate, t);
|
||||
t.adsPrerollEndedProxy = $.proxy(t.adsPrerollEnded, t);
|
||||
|
||||
// check for start
|
||||
t.media.addEventListener('play', t.adsMediaTryingToStartProxy );
|
||||
t.media.addEventListener('playing', t.adsMediaTryingToStartProxy );
|
||||
t.media.addEventListener('canplay', t.adsMediaTryingToStartProxy );
|
||||
t.media.addEventListener('loadedmetadata', t.adsMediaTryingToStartProxy );
|
||||
|
||||
console.log('setup ads', t.options.adsPrerollMediaUrl);
|
||||
|
||||
if (t.options.adsPrerollMediaUrl != '') {
|
||||
t.adsStartPreroll();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
adsMediaTryingToStart: function() {
|
||||
|
||||
var t = this;
|
||||
|
||||
// make sure to pause until the ad data is loaded
|
||||
if (t.adsDataIsLoading && !t.media.paused) {
|
||||
t.media.pause();
|
||||
}
|
||||
|
||||
t.adsPlayerHasStarted = true;
|
||||
},
|
||||
|
||||
adsStartPreroll: function() {
|
||||
|
||||
var t = this;
|
||||
|
||||
console.log('adsStartPreroll', 'url', t.options.adsPrerollMediaUrl);
|
||||
|
||||
|
||||
t.media.addEventListener('loadedmetadata', t.adsPrerollMetaProxy );
|
||||
t.media.addEventListener('playing', t.adsPrerollStartedProxy );
|
||||
t.media.addEventListener('ended', t.adsPrerollEndedProxy )
|
||||
t.media.addEventListener('timeupdate', t.adsPrerollUpdateProxy );
|
||||
|
||||
// change URLs to the preroll ad
|
||||
t.adsCurrentMediaUrl = t.media.src;
|
||||
t.adsCurrentMediaDuration = t.media.duration;
|
||||
|
||||
t.media.setSrc(t.options.adsPrerollMediaUrl);
|
||||
t.media.load();
|
||||
|
||||
// if autoplay was on, or if the user pressed play
|
||||
// while the ad data was still loading, then start the ad right away
|
||||
if (t.adsPlayerHasStarted) {
|
||||
t.media.play();
|
||||
}
|
||||
},
|
||||
|
||||
adsPrerollMeta: function() {
|
||||
|
||||
var t = this,
|
||||
newDuration = 0;
|
||||
|
||||
console.log('loadedmetadata', t.media.duration, t.adsCurrentMediaDuration);
|
||||
|
||||
// if duration has been set, show that
|
||||
if (t.options.duration > 0) {
|
||||
newDuration = t.options.duration;
|
||||
} else if (!isNaN(t.adsCurrentMediaDuration)) {
|
||||
newDuration = t.adsCurrentMediaDuration;
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
t.controls.find('.mejs-duration').html(
|
||||
mejs.Utility.secondsToTimeCode(newDuration, t.options.alwaysShowHours || newDuration > 3600, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25)
|
||||
);
|
||||
}, 250);
|
||||
},
|
||||
|
||||
adsPrerollStarted: function() {
|
||||
console.log('adsPrerollStarted');
|
||||
|
||||
var t = this;
|
||||
t.media.removeEventListener('playing', t.adsPrerollStartedProxy);
|
||||
|
||||
// turn off controls until the preroll is done
|
||||
t.disableControls();
|
||||
t.hideControls();
|
||||
|
||||
// enable clicking through
|
||||
t.adsLayer.show();
|
||||
if (t.options.adsPrerollAdUrl != '') {
|
||||
t.adsLayer.find('a').attr('href', t.options.adsPrerollAdUrl);
|
||||
}
|
||||
|
||||
// possibly allow the skip button to work
|
||||
if (t.options.adsPrerollAdEnableSkip) {
|
||||
t.adsSkipBlock.show();
|
||||
|
||||
if (t.options.adsPrerollAdSkipSeconds > 0) {
|
||||
t.adsSkipMessage.html('Skip in ' + t.options.adsPrerollAdSkipSeconds.toString() + ' seconds.').show();
|
||||
t.adsSkipButton.hide();
|
||||
} else {
|
||||
t.adsSkipMessage.hide();
|
||||
t.adsSkipButton.show();
|
||||
}
|
||||
} else {
|
||||
t.adsSkipBlock.hide();
|
||||
}
|
||||
|
||||
// send click events
|
||||
t.container.trigger('mejsprerollstarted');
|
||||
},
|
||||
|
||||
adsPrerollUpdate: function() {
|
||||
//console.log('adsPrerollUpdate');
|
||||
|
||||
var t = this;
|
||||
|
||||
if (t.options.adsPrerollAdEnableSkip && t.options.adsPrerollAdSkipSeconds > 0) {
|
||||
// update message
|
||||
if (t.media.currentTime > t.options.adsPrerollAdSkipSeconds) {
|
||||
t.adsSkipButton.show();
|
||||
t.adsSkipMessage.hide();
|
||||
} else {
|
||||
t.adsSkipMessage.html('Skip in ' + Math.round( t.options.adsPrerollAdSkipSeconds - t.media.currentTime ).toString() + ' seconds.')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
t.container.trigger('mejsprerolltimeupdate');
|
||||
},
|
||||
|
||||
adsPrerollEnded: function() {
|
||||
console.log('adsPrerollEnded');
|
||||
|
||||
var t = this;
|
||||
|
||||
t.container.trigger('mejsprerollended');
|
||||
|
||||
t.adRestoreMainMedia();
|
||||
},
|
||||
|
||||
adRestoreMainMedia: function() {
|
||||
|
||||
console.log('adRestoreMainMedia', this.adsCurrentMediaUrl);
|
||||
|
||||
var t = this;
|
||||
|
||||
t.media.setSrc(t.adsCurrentMediaUrl);
|
||||
setTimeout(function() {
|
||||
t.media.load();
|
||||
t.media.play();
|
||||
}, 10);
|
||||
|
||||
t.enableControls();
|
||||
t.showControls();
|
||||
|
||||
t.adsLayer.hide();
|
||||
|
||||
t.media.removeEventListener('ended', t.adsPrerollEndedProxy);
|
||||
t.media.removeEventListener('loadedmetadata', t.adsPrerollMetaProxy);
|
||||
t.media.removeEventListener('timeupdate', t.adsPrerollUpdateProxy);
|
||||
|
||||
t.container.trigger('mejsprerollmainstarted');
|
||||
},
|
||||
|
||||
adsAdClick: function(e) {
|
||||
console.log('adsAdClicked');
|
||||
|
||||
var t = this;
|
||||
|
||||
if (t.media.paused) {
|
||||
t.media.play();
|
||||
} else {
|
||||
t.media.pause();
|
||||
}
|
||||
|
||||
t.container.trigger('mejsprerolladsclicked');
|
||||
},
|
||||
|
||||
adsSkipClick: function() {
|
||||
console.log('adsSkipClick');
|
||||
var t = this;
|
||||
|
||||
t.container.trigger('mejsprerollskipclicked');
|
||||
t.container.trigger('mejsprerollended');
|
||||
|
||||
t.adRestoreMainMedia();
|
||||
},
|
||||
|
||||
// fires off fake XHR requests
|
||||
adsLoadUrl: function(url) {
|
||||
console.log('adsLoadUrl', url);
|
||||
|
||||
var img = new Image(),
|
||||
rnd = Math.round(Math.random()*100000);
|
||||
|
||||
img.src = url + ((url.indexOf('?') > 0) ? '&' : '?') + 'random' + rnd + '=' + rnd;
|
||||
img.loaded = function() {
|
||||
img = null;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})(mejs.$);
|
||||
@@ -0,0 +1,435 @@
|
||||
(function($) {
|
||||
|
||||
$.extend(mejs.MepDefaults, {
|
||||
backlightBackground: [0,0,0],
|
||||
backlightHorizontalLights: 5,
|
||||
backlightVerticalLights: 5,
|
||||
backlightSize: 50,
|
||||
backlightTimeout: 200
|
||||
});
|
||||
|
||||
$.extend(MediaElementPlayer.prototype, {
|
||||
buildbacklight : function(player, controls, layers, media) {
|
||||
if (!player.isVideo)
|
||||
return;
|
||||
|
||||
//http://www.splashnology.com/blog/html5/382.html
|
||||
|
||||
var
|
||||
mediaContainer = player.container.find('.mejs-mediaelement').parent(),
|
||||
border = $('<div class="mejs-border"></div>')
|
||||
.prependTo(mediaContainer)
|
||||
.css('position','absolute')
|
||||
.css('top','-10px')
|
||||
.css('left','-10px')
|
||||
.css('border','solid 10px #010101')
|
||||
.width(player.width).height(player.height),
|
||||
glowBase = $('<div class="mejs-backlight-glow"></div>')
|
||||
.prependTo(mediaContainer)
|
||||
.css('position','absolute')
|
||||
.css('display','none')
|
||||
.css('top',0)
|
||||
.css('left',0)
|
||||
.width(player.width).height(player.height),
|
||||
base = $('<div class="mejs-backlight"></div>')
|
||||
.prependTo(mediaContainer)
|
||||
.css('position','absolute')
|
||||
.css('top',0)
|
||||
.css('left',0)
|
||||
.width(player.width).height(player.height),
|
||||
|
||||
i,
|
||||
copyCanvas = document.createElement('canvas'),
|
||||
copyContext = copyCanvas.getContext('2d'),
|
||||
pixels,
|
||||
keepUpdating = true,
|
||||
isActive = true,
|
||||
timer = null,
|
||||
glowCanvas = document.createElement('canvas'),
|
||||
glowContext = glowCanvas.getContext('2d'),
|
||||
size = player.options.backlightSize,
|
||||
backgroundColor = player.options.backlightBackground,
|
||||
gradient,
|
||||
width = player.width,
|
||||
height = player.height;
|
||||
|
||||
// set sizes
|
||||
copyCanvas.width = width;
|
||||
copyCanvas.height = height;
|
||||
glowCanvas.width = width + size + size;
|
||||
glowCanvas.height = height + size + size;
|
||||
|
||||
// draw glow overlay
|
||||
// top
|
||||
gradient = addGlow(backgroundColor,glowContext.createLinearGradient(size, size, size, 0));
|
||||
glowContext.fillStyle = gradient;
|
||||
glowContext.fillRect(size, size, width, -size);
|
||||
|
||||
// tr
|
||||
gradient = addGlow(backgroundColor,glowContext.createRadialGradient(width+size, size, 0, width+size, size, size));
|
||||
glowContext.fillStyle = gradient;
|
||||
glowContext.fillRect(width+size, size, size, -size);
|
||||
|
||||
// right
|
||||
gradient = addGlow(backgroundColor,glowContext.createLinearGradient(width+size, size, width+size+size, size));
|
||||
glowContext.fillStyle = gradient;
|
||||
glowContext.fillRect(width+size, size, size, height);
|
||||
|
||||
// br
|
||||
gradient = addGlow(backgroundColor,glowContext.createRadialGradient(width+size, height+size, 0, width+size, height+size, size));
|
||||
glowContext.fillStyle = gradient;
|
||||
glowContext.fillRect(width+size, height+size, size, size);
|
||||
|
||||
// bottom
|
||||
var gradient = addGlow(backgroundColor,glowContext.createLinearGradient(size, size+height, size, size+height+size));
|
||||
glowContext.fillStyle = gradient;
|
||||
glowContext.fillRect(size, size+height, width, size);
|
||||
|
||||
// bl
|
||||
gradient = addGlow(backgroundColor,glowContext.createRadialGradient(size, height+size, 0, size, height+size, size));
|
||||
glowContext.fillStyle = gradient;
|
||||
glowContext.fillRect(0, height+size, size, size);
|
||||
|
||||
// left
|
||||
gradient = addGlow(backgroundColor,glowContext.createLinearGradient(size, size, 0, size));
|
||||
glowContext.fillStyle = gradient;
|
||||
glowContext.fillRect(size, size, -size, height);
|
||||
|
||||
// tl
|
||||
gradient = addGlow(backgroundColor,glowContext.createRadialGradient(size, size, 0, size, size, size));
|
||||
glowContext.fillStyle = gradient;
|
||||
glowContext.fillRect(0, 0, size, size);
|
||||
|
||||
$(glowCanvas)
|
||||
.css('position','absolute')
|
||||
.css('top',-size)
|
||||
.css('left',-size)
|
||||
.appendTo(glowBase);
|
||||
|
||||
|
||||
// add toggle control
|
||||
$('<div class="mejs-backlight-button mejs-backlight-active"><span></span></div>')
|
||||
.appendTo(controls)
|
||||
.click(function() {
|
||||
if (isActive) {
|
||||
delete timer;
|
||||
timer = null;
|
||||
base.hide();
|
||||
glowBase.hide();
|
||||
$(this)
|
||||
.removeClass('mejs-backlight-active')
|
||||
.addClass('mejs-backlight-inactive')
|
||||
} else {
|
||||
updateLights();
|
||||
base.show();
|
||||
glowBase.show();
|
||||
$(this)
|
||||
.removeClass('mejs-backlight-inactive')
|
||||
.addClass('mejs-backlight-active')
|
||||
}
|
||||
isActive = !isActive;
|
||||
});
|
||||
|
||||
|
||||
// http://www.splashnology.com/blog/html5/382.html
|
||||
function updateLights() {
|
||||
|
||||
// get a copy of video
|
||||
copyContext.drawImage(media, 0, 0, media.width, media.height);
|
||||
|
||||
// create the gradient lights
|
||||
addLights(base, copyCanvas, copyContext,
|
||||
player.options.backlightVerticalLights,
|
||||
player.options.backlightHorizontalLights,
|
||||
player.options.backlightSize,
|
||||
30);
|
||||
|
||||
if (keepUpdating && isActive) {
|
||||
timer = setTimeout(updateLights, player.options.backlightTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//setTimeout(updateLights, timeOut);
|
||||
|
||||
media.addEventListener('play',function() {
|
||||
if (isActive) {
|
||||
keepUpdating = true;
|
||||
updateLights();
|
||||
glowBase.css('display','');
|
||||
}
|
||||
}, false);
|
||||
media.addEventListener('pause',function() {
|
||||
keepUpdating = false;
|
||||
}, false);
|
||||
media.addEventListener('ended',function() {
|
||||
keepUpdating = false;
|
||||
}, false);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
function addLights(base, canvas, context, vBlocks, hBlocks, size, depth) {
|
||||
base.empty();
|
||||
|
||||
var
|
||||
lightsCanvas = document.createElement('canvas'),
|
||||
lightsContext = lightsCanvas.getContext('2d'),
|
||||
width = canvas.width,
|
||||
height = canvas.height,
|
||||
g,
|
||||
topLights = getMidColors(canvas, context, hBlocks, depth, 'top'),
|
||||
bottomLights = getMidColors(canvas, context, hBlocks, depth, 'bottom'),
|
||||
leftLights = getMidColors(canvas, context, vBlocks, depth, 'left'),
|
||||
rightLights = getMidColors(canvas, context, vBlocks, depth, 'right'),
|
||||
corners = [],
|
||||
stopSize = 0;
|
||||
|
||||
lightsCanvas.width = width + size + size;
|
||||
lightsCanvas.height = height + size + size;
|
||||
lightsContext.globalCompositeOperation = 'xor'; //'darker'; //'lighter';
|
||||
|
||||
// draw four gradients
|
||||
// create corners
|
||||
corners.push(averageColor(topLights[topLights.length-1], rightLights[0]) );
|
||||
corners.push(averageColor(bottomLights[bottomLights.length-1], rightLights[rightLights.length-1]) );
|
||||
corners.push(averageColor(bottomLights[0], leftLights[leftLights.length-1]) );
|
||||
corners.push(averageColor(topLights[0], leftLights[0]) );
|
||||
|
||||
// top
|
||||
stopSize = 1 / topLights.length;
|
||||
gradient = context.createLinearGradient(size, size, width+size, size);
|
||||
gradient.addColorStop(0, 'rgb(' + adjustColor(corners[3]).join(',') + ')');
|
||||
for (var i = 0, il = topLights.length; i < il; i++) {
|
||||
gradient.addColorStop(i * stopSize + stopSize/2, 'rgb(' + adjustColor(topLights[i]).join(',') + ')');
|
||||
}
|
||||
gradient.addColorStop(1.0, 'rgb(' + adjustColor(corners[0]).join(',') + ')');
|
||||
lightsContext.fillStyle = gradient;
|
||||
lightsContext.fillRect(size, 0, width, size);
|
||||
|
||||
// right
|
||||
gradient = context.createLinearGradient(size+width, size, size+width, size+height);
|
||||
gradient.addColorStop(0, 'rgb(' + adjustColor(corners[0]).join(',') + ')');
|
||||
for (var i = 0, il = rightLights.length; i < il; i++) {
|
||||
gradient.addColorStop(i * stopSize + stopSize/2, 'rgb(' + adjustColor(rightLights[i]).join(',') + ')');
|
||||
}
|
||||
gradient.addColorStop(1.0, 'rgb(' + adjustColor(corners[1]).join(',') + ')');
|
||||
lightsContext.fillStyle = gradient;
|
||||
lightsContext.fillRect(size+width, size, size+width+size, height);
|
||||
|
||||
|
||||
// bottom
|
||||
gradient = context.createLinearGradient(size, size+height, size+width, size+height);
|
||||
gradient.addColorStop(0, 'rgb(' + adjustColor(corners[2]).join(',') + ')');
|
||||
for (var i = 0, il = bottomLights.length; i < il; i++) {
|
||||
gradient.addColorStop(i * stopSize + stopSize/2, 'rgb(' + adjustColor(bottomLights[i]).join(',') + ')');
|
||||
}
|
||||
gradient.addColorStop(1.0, 'rgb(' + adjustColor(corners[1]).join(',') + ')');
|
||||
lightsContext.fillStyle = gradient;
|
||||
lightsContext.fillRect(size, size+height, width, size);
|
||||
|
||||
// left
|
||||
gradient = context.createLinearGradient(size, size, size, size+height);
|
||||
gradient.addColorStop(0, 'rgb(' + adjustColor(corners[3]).join(',') + ')');
|
||||
for (var i = 0, il = leftLights.length; i < il; i++) {
|
||||
gradient.addColorStop(i * stopSize + stopSize/2, 'rgb(' + adjustColor(leftLights[i]).join(',') + ')');
|
||||
}
|
||||
gradient.addColorStop(1.0, 'rgb(' + adjustColor(corners[2]).join(',') + ')');
|
||||
lightsContext.fillStyle = gradient;
|
||||
lightsContext.fillRect(0, size, size, height);
|
||||
|
||||
// corners
|
||||
|
||||
// top right
|
||||
lightsContext.fillStyle = 'rgb(' + adjustColor(corners[0]).join(',') + ')';
|
||||
lightsContext.fillRect(width+size, 0, size+width+size, size);
|
||||
|
||||
// bottom right
|
||||
lightsContext.fillStyle = 'rgb(' + adjustColor(corners[1]).join(',') + ')';
|
||||
lightsContext.fillRect(width+size, size+height, size+width+size, size+height+size);
|
||||
|
||||
// bottom left
|
||||
lightsContext.fillStyle = 'rgb(' + adjustColor(corners[2]).join(',') + ')';
|
||||
lightsContext.fillRect(0, size+height, size, size+height+size);
|
||||
|
||||
// top left
|
||||
lightsContext.fillStyle = 'rgb(' + adjustColor(corners[3]).join(',') + ')';
|
||||
lightsContext.fillRect(0, 0, size, size);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$(lightsCanvas)
|
||||
.css('position','absolute')
|
||||
.css('top',-size)
|
||||
.css('left',-size)
|
||||
.appendTo(base);
|
||||
}
|
||||
|
||||
function addGlow(color, g) {
|
||||
g.addColorStop(0.0, 'rgba(' + color.join(',') + ',0)');
|
||||
g.addColorStop(1.0, 'rgba(' + color.join(',') + ',1)');
|
||||
return g;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function getMidColors(canvas, context, blocks, blockDepth, side) {
|
||||
var width = canvas.width,
|
||||
height = canvas.height,
|
||||
blockHeight = (side == 'top' || side == 'bottom') ? blockDepth : Math.ceil(height / blocks), // height of the analyzed block
|
||||
blockWidth = (side == 'top' || side == 'bottom') ? Math.ceil(width / blocks) : blockDepth,
|
||||
result = [],
|
||||
imgdata,
|
||||
i;
|
||||
|
||||
if (side == 'top' || side == 'bottom') {
|
||||
for (i = 0; i < blocks; i++) {
|
||||
try {
|
||||
imgdata = context.getImageData(i*blockWidth, (side == 'top') ? 0 : height - blockHeight , blockWidth, blockHeight);
|
||||
result.push(
|
||||
calcMidColor(imgdata.data)
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
for (i = 0; i < blocks; i++) {
|
||||
try {
|
||||
imgdata = context.getImageData( (side == 'right') ? width - blockWidth : 0, i*blockHeight, blockWidth, blockHeight);
|
||||
result.push(
|
||||
calcMidColor(imgdata.data)
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function averageColor(c1,c2) {
|
||||
var result =
|
||||
[(c1[0] + c2[0]) / 2,
|
||||
(c1[1] + c2[1]) / 2,
|
||||
(c1[2] + c2[2]) / 2];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// average color for a block
|
||||
function calcMidColorVertical(data, from, to) {
|
||||
var result = [0, 0, 0];
|
||||
var totalPixels = (to - from) / 4;
|
||||
|
||||
for (var i = from; i <= to; i += 4) {
|
||||
result[0] += data[i];
|
||||
result[1] += data[i + 1];
|
||||
result[2] += data[i + 2];
|
||||
}
|
||||
|
||||
result[0] = Math.round(result[0] / totalPixels);
|
||||
result[1] = Math.round(result[1] / totalPixels);
|
||||
result[2] = Math.round(result[2] / totalPixels);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// average color for a block
|
||||
function calcMidColor(data) {
|
||||
var result = [0, 0, 0];
|
||||
var totalPixels = data.length;
|
||||
|
||||
for (var i = 0; i < totalPixels; i += 4) {
|
||||
result[0] += data[i];
|
||||
result[1] += data[i + 1];
|
||||
result[2] += data[i + 2];
|
||||
}
|
||||
|
||||
result[0] = Math.round(result[0] / totalPixels);
|
||||
result[1] = Math.round(result[1] / totalPixels);
|
||||
result[2] = Math.round(result[2] / totalPixels);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function adjustColor(color) {
|
||||
//if (color[0] <= 2 && color[2] <= 2 && color[3] <= 2)
|
||||
// return color;
|
||||
|
||||
color = rgb2hsv(color);
|
||||
color[1] = Math.min(100, color[1] * 1.2); //1.4); // saturation
|
||||
color[2] = 80; //Math.min(100, color[2] * 2.7); //2.7); // brightness
|
||||
return hsv2rgb(color);
|
||||
}
|
||||
|
||||
function rgb2hsv(color) {
|
||||
var r = color[0] / 255,
|
||||
g = color[1] / 255,
|
||||
b = color[2] / 255,
|
||||
|
||||
x, val, d1, d2, hue, sat, val;
|
||||
|
||||
x = Math.min(Math.min(r, g), b);
|
||||
val = Math.max(Math.max(r, g), b);
|
||||
//if (x == val)
|
||||
// throw Error('h is undefined');
|
||||
|
||||
d1 = (r == x) ? g-b : ((g == x) ? b-r : r-g);
|
||||
d2 = (r == x) ? 3 : ((g == x) ? 5 : 1);
|
||||
|
||||
hue = Math.floor((d2 - d1 / (val - x)) * 60) % 360;
|
||||
sat = Math.floor(((val - x) / val) * 100);
|
||||
val = Math.floor(val * 100);
|
||||
return [hue, sat, val];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convers HSV color to RGB model
|
||||
* @param {Number[]} RGB color
|
||||
* @return {Number[]} HSV color
|
||||
*/
|
||||
function hsv2rgb(color) {
|
||||
var h = color[0],
|
||||
s = color[1],
|
||||
v = color[2];
|
||||
|
||||
var r, g, a, b, c, s = s / 100, v = v / 100, h = h / 360;
|
||||
|
||||
if (s > 0) {
|
||||
if (h >= 1) h=0;
|
||||
|
||||
h = 6 * h;
|
||||
var f = h - Math.floor(h);
|
||||
a = Math.round(255 * v * (1 - s));
|
||||
b = Math.round(255 * v * (1 - (s * f)));
|
||||
c = Math.round(255 * v * (1 - (s * (1 - f))));
|
||||
v = Math.round(255 * v);
|
||||
|
||||
switch (Math.floor(h)) {
|
||||
case 0: r = v; g = c; b = a; break;
|
||||
case 1: r = b; g = v; b = a; break;
|
||||
case 2: r = a; g = v; b = c; break;
|
||||
case 3: r = a; g = b; b = v; break;
|
||||
case 4: r = c; g = a; b = v; break;
|
||||
case 5: r = v; g = a; b = b; break;
|
||||
}
|
||||
|
||||
return [r || 0, g || 0, b || 0];
|
||||
|
||||
} else {
|
||||
v = Math.round(v * 255);
|
||||
return [v, v, v];
|
||||
}
|
||||
}
|
||||
|
||||
})(mejs.$);
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* 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 mejs.i18n.t('Turn off Fullscreen');
|
||||
} else {
|
||||
return mejs.i18n.t('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 mejs.i18n.t('Unmute');
|
||||
} else {
|
||||
return mejs.i18n.t('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 mejs.i18n.t('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();
|
||||
|
||||
});
|
||||
},
|
||||
|
||||
cleancontextmenu: function(player) {
|
||||
player.contextMenu.remove();
|
||||
},
|
||||
|
||||
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.$);
|
||||
@@ -0,0 +1,12 @@
|
||||
(function($) {
|
||||
|
||||
$.extend(MediaElementPlayer.prototype, {
|
||||
buildendedhtml: function(player, controls, layers, media) {
|
||||
if (!player.isVideo)
|
||||
return;
|
||||
|
||||
// add postroll
|
||||
}
|
||||
});
|
||||
|
||||
})(mejs.$);
|
||||
@@ -0,0 +1,469 @@
|
||||
(function($) {
|
||||
|
||||
$.extend(mejs.MepDefaults, {
|
||||
usePluginFullScreen: true,
|
||||
newWindowCallback: function() { return '';},
|
||||
fullscreenText: mejs.i18n.t('Fullscreen')
|
||||
});
|
||||
|
||||
$.extend(MediaElementPlayer.prototype, {
|
||||
|
||||
isFullScreen: false,
|
||||
|
||||
isNativeFullScreen: false,
|
||||
|
||||
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 func = function(e) {
|
||||
if (player.isFullScreen) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (mejs.MediaFeatures.hasMozNativeFullScreen) {
|
||||
player.globalBind(mejs.MediaFeatures.fullScreenEventName, func);
|
||||
} else {
|
||||
player.container.bind(mejs.MediaFeatures.fullScreenEventName, func);
|
||||
}
|
||||
}
|
||||
|
||||
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 + '" aria-label="' + 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
|
||||
for (var i in hoverDivs) {
|
||||
hoverDivs[i].hide();
|
||||
}
|
||||
|
||||
// restore the control bar
|
||||
fullscreenBtn.css('pointer-events', '');
|
||||
t.controls.css('pointer-events', '');
|
||||
|
||||
// prevent clicks from pausing video
|
||||
t.media.removeEventListener('click', t.clickToPlayPauseCallback);
|
||||
|
||||
// store for later
|
||||
fullscreenIsDisabled = false;
|
||||
}
|
||||
},
|
||||
hoverDivs = {},
|
||||
hoverDivNames = ['top', 'left', 'right', 'bottom'],
|
||||
i, len,
|
||||
positionHoverDivs = function() {
|
||||
var fullScreenBtnOffsetLeft = fullscreenBtn.offset().left - t.container.offset().left,
|
||||
fullScreenBtnOffsetTop = fullscreenBtn.offset().top - t.container.offset().top,
|
||||
fullScreenBtnWidth = fullscreenBtn.outerWidth(true),
|
||||
fullScreenBtnHeight = fullscreenBtn.outerHeight(true),
|
||||
containerWidth = t.container.width(),
|
||||
containerHeight = t.container.height();
|
||||
|
||||
for (i in hoverDivs) {
|
||||
hoverDivs[i].css({position: 'absolute', top: 0, left: 0}); //, backgroundColor: '#f00'});
|
||||
}
|
||||
|
||||
// over video, but not controls
|
||||
hoverDivs['top']
|
||||
.width( containerWidth )
|
||||
.height( fullScreenBtnOffsetTop );
|
||||
|
||||
// over controls, but not the fullscreen button
|
||||
hoverDivs['left']
|
||||
.width( fullScreenBtnOffsetLeft )
|
||||
.height( fullScreenBtnHeight )
|
||||
.css({top: fullScreenBtnOffsetTop});
|
||||
|
||||
// after the fullscreen button
|
||||
hoverDivs['right']
|
||||
.width( containerWidth - fullScreenBtnOffsetLeft - fullScreenBtnWidth )
|
||||
.height( fullScreenBtnHeight )
|
||||
.css({top: fullScreenBtnOffsetTop,
|
||||
left: fullScreenBtnOffsetLeft + fullScreenBtnWidth});
|
||||
|
||||
// under the fullscreen button
|
||||
hoverDivs['bottom']
|
||||
.width( containerWidth )
|
||||
.height( containerHeight - fullScreenBtnHeight - fullScreenBtnOffsetTop )
|
||||
.css({top: fullScreenBtnOffsetTop + fullScreenBtnHeight});
|
||||
};
|
||||
|
||||
t.globalBind('resize', function() {
|
||||
positionHoverDivs();
|
||||
});
|
||||
|
||||
for (i = 0, len = hoverDivNames.length; i < len; i++) {
|
||||
hoverDivs[hoverDivNames[i]] = $('<div class="mejs-fullscreen-hover" />').appendTo(t.container).mouseover(restoreControls).hide();
|
||||
}
|
||||
|
||||
// on hover, kill the fullscreen button's HTML handling, allowing clicks down to Flash
|
||||
fullscreenBtn.on('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');
|
||||
|
||||
// restore click-to-play
|
||||
t.media.addEventListener('click', t.clickToPlayPauseCallback);
|
||||
|
||||
// show the divs that will restore things
|
||||
for (i in hoverDivs) {
|
||||
hoverDivs[i].show();
|
||||
}
|
||||
|
||||
positionHoverDivs();
|
||||
|
||||
fullscreenIsDisabled = true;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// restore controls anytime the user enters or leaves fullscreen
|
||||
media.addEventListener('fullscreenchange', function(e) {
|
||||
t.isFullScreen = !t.isFullScreen;
|
||||
// don't allow plugin click to pause video - messes with
|
||||
// plugin's controls
|
||||
if (t.isFullScreen) {
|
||||
t.media.removeEventListener('click', t.clickToPlayPauseCallback);
|
||||
} else {
|
||||
t.media.addEventListener('click', t.clickToPlayPauseCallback);
|
||||
}
|
||||
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
|
||||
|
||||
t.globalBind('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
|
||||
.on('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);
|
||||
|
||||
})
|
||||
.on('mouseout', function() {
|
||||
|
||||
if (hideTimeout !== null) {
|
||||
clearTimeout(hideTimeout);
|
||||
delete hideTimeout;
|
||||
}
|
||||
|
||||
hideTimeout = setTimeout(function() {
|
||||
media.hideFullscreenButton();
|
||||
}, 1500);
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
player.fullscreenBtn = fullscreenBtn;
|
||||
|
||||
t.globalBind('keydown',function (e) {
|
||||
if (((mejs.MediaFeatures.hasTrueNativeFullScreen && mejs.MediaFeatures.isFullScreen()) || t.isFullScreen) && e.keyCode == 27) {
|
||||
player.exitFullScreen();
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
cleanfullscreen: function(player) {
|
||||
player.exitFullScreen();
|
||||
},
|
||||
|
||||
containerSizeTimeout: null,
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// set it to not show scroll bars so 100% will work
|
||||
$(document.documentElement).addClass('mejs-fullscreen');
|
||||
|
||||
// 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) {
|
||||
t.containerSizeTimeout = setTimeout(function() {
|
||||
t.container.css({width: '100%', height: '100%'});
|
||||
t.setControlsSize();
|
||||
}, 500);
|
||||
//}
|
||||
|
||||
if (t.media.pluginType === 'native') {
|
||||
t.$media
|
||||
.width('100%')
|
||||
.height('100%');
|
||||
} else {
|
||||
t.container.find('.mejs-shim')
|
||||
.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;
|
||||
|
||||
// Prevent container from attempting to stretch a second time
|
||||
clearTimeout(t.containerSizeTimeout);
|
||||
|
||||
// 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).removeClass('mejs-fullscreen');
|
||||
|
||||
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.media.pluginType === 'native') {
|
||||
t.$media
|
||||
.width(normalWidth)
|
||||
.height(normalHeight);
|
||||
} else {
|
||||
t.container.find('.mejs-shim')
|
||||
.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.$);
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Google Analytics Plugin
|
||||
* Requires
|
||||
*
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
$.extend(mejs.MepDefaults, {
|
||||
googleAnalyticsTitle: '',
|
||||
googleAnalyticsCategory: 'Videos',
|
||||
googleAnalyticsEventPlay: 'Play',
|
||||
googleAnalyticsEventPause: 'Pause',
|
||||
googleAnalyticsEventEnded: 'Ended',
|
||||
googleAnalyticsEventTime: 'Time'
|
||||
});
|
||||
|
||||
|
||||
$.extend(MediaElementPlayer.prototype, {
|
||||
buildgoogleanalytics: function(player, controls, layers, media) {
|
||||
|
||||
media.addEventListener('play', function() {
|
||||
if (typeof _gaq != 'undefined') {
|
||||
_gaq.push(['_trackEvent',
|
||||
player.options.googleAnalyticsCategory,
|
||||
player.options.googleAnalyticsEventPlay,
|
||||
(player.options.googleAnalyticsTitle === '') ? player.currentSrc : player.options.googleAnalyticsTitle
|
||||
]);
|
||||
}
|
||||
}, false);
|
||||
|
||||
media.addEventListener('pause', function() {
|
||||
if (typeof _gaq != 'undefined') {
|
||||
_gaq.push(['_trackEvent',
|
||||
player.options.googleAnalyticsCategory,
|
||||
player.options.googleAnalyticsEventPause,
|
||||
(player.options.googleAnalyticsTitle === '') ? player.currentSrc : player.options.googleAnalyticsTitle
|
||||
]);
|
||||
}
|
||||
}, false);
|
||||
|
||||
media.addEventListener('ended', function() {
|
||||
if (typeof _gaq != 'undefined') {
|
||||
_gaq.push(['_trackEvent',
|
||||
player.options.googleAnalyticsCategory,
|
||||
player.options.googleAnalyticsEventEnded,
|
||||
(player.options.googleAnalyticsTitle === '') ? player.currentSrc : player.options.googleAnalyticsTitle
|
||||
]);
|
||||
}
|
||||
}, false);
|
||||
|
||||
/*
|
||||
media.addEventListener('timeupdate', function() {
|
||||
if (typeof _gaq != 'undefined') {
|
||||
_gaq.push(['_trackEvent',
|
||||
player.options.googleAnalyticsCategory,
|
||||
player.options.googleAnalyticsEventEnded,
|
||||
player.options.googleAnalyticsTime,
|
||||
(player.options.googleAnalyticsTitle === '') ? player.currentSrc : player.options.googleAnalyticsTitle,
|
||||
player.currentTime
|
||||
]);
|
||||
}
|
||||
}, true);
|
||||
*/
|
||||
}
|
||||
});
|
||||
|
||||
})(mejs.$);
|
||||
@@ -0,0 +1,26 @@
|
||||
(function($) {
|
||||
// loop toggle
|
||||
$.extend(MediaElementPlayer.prototype, {
|
||||
buildloop: function(player, controls, layers, media) {
|
||||
var
|
||||
t = this,
|
||||
// create the loop button
|
||||
loop =
|
||||
$('<div class="mejs-button mejs-loop-button ' + ((player.options.loop) ? 'mejs-loop-on' : 'mejs-loop-off') + '">' +
|
||||
'<button type="button" aria-controls="' + t.id + '" title="Toggle Loop" aria-label="Toggle Loop"></button>' +
|
||||
'</div>')
|
||||
// append it to the toolbar
|
||||
.appendTo(controls)
|
||||
// add a click toggle event
|
||||
.click(function() {
|
||||
player.options.loop = !player.options.loop;
|
||||
if (player.options.loop) {
|
||||
loop.removeClass('mejs-loop-off').addClass('mejs-loop-on');
|
||||
} else {
|
||||
loop.removeClass('mejs-loop-on').addClass('mejs-loop-off');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
})(mejs.$);
|
||||
@@ -0,0 +1,12 @@
|
||||
(function($) {
|
||||
|
||||
$.extend(MediaElementPlayer.prototype, {
|
||||
buildplaylist : function(player, controls, layers, media) {
|
||||
if (!player.isVideo)
|
||||
return;
|
||||
|
||||
// add speed controls
|
||||
}
|
||||
});
|
||||
|
||||
})(mejs.$);
|
||||
@@ -0,0 +1,46 @@
|
||||
(function($) {
|
||||
|
||||
$.extend(mejs.MepDefaults, {
|
||||
playpauseText: mejs.i18n.t('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 + '" aria-label="' + 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.$);
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Postroll plugin
|
||||
*/
|
||||
(function($) {
|
||||
|
||||
$.extend(mejs.MepDefaults, {
|
||||
postrollCloseText: mejs.i18n.t('Close')
|
||||
});
|
||||
|
||||
// Postroll
|
||||
$.extend(MediaElementPlayer.prototype, {
|
||||
buildpostroll: function(player, controls, layers, media) {
|
||||
var
|
||||
t = this,
|
||||
postrollLink = t.container.find('link[rel="postroll"]').attr('href');
|
||||
|
||||
if (typeof postrollLink !== 'undefined') {
|
||||
player.postroll =
|
||||
$('<div class="mejs-postroll-layer mejs-layer"><a class="mejs-postroll-close" onclick="$(this).parent().hide();return false;">' + t.options.postrollCloseText + '</a><div class="mejs-postroll-layer-content"></div></div>').prependTo(layers).hide();
|
||||
|
||||
t.media.addEventListener('ended', function (e) {
|
||||
$.ajax({
|
||||
dataType: 'html',
|
||||
url: postrollLink,
|
||||
success: function (data, textStatus) {
|
||||
layers.find('.mejs-postroll-layer-content').html(data);
|
||||
}
|
||||
});
|
||||
player.postroll.show();
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
})(mejs.$);
|
||||
@@ -0,0 +1,173 @@
|
||||
(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(true),
|
||||
percentage = 0,
|
||||
newTime = 0,
|
||||
pos = 0;
|
||||
|
||||
|
||||
if (media.duration) {
|
||||
if (x < offset.left) {
|
||||
x = offset.left;
|
||||
} else if (x > width + offset.left) {
|
||||
x = width + offset.left;
|
||||
}
|
||||
|
||||
pos = x - offset.left;
|
||||
percentage = (pos / width);
|
||||
newTime = (percentage <= 0.02) ? 0 : percentage * media.duration;
|
||||
|
||||
// seek to where the mouse is
|
||||
if (mouseIsDown && newTime !== media.currentTime) {
|
||||
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);
|
||||
t.globalBind('mousemove.dur', function(e) {
|
||||
handleMouseMove(e);
|
||||
});
|
||||
t.globalBind('mouseup.dur', function (e) {
|
||||
mouseIsDown = false;
|
||||
timefloat.hide();
|
||||
t.globalUnbind('.dur');
|
||||
});
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.bind('mouseenter', function(e) {
|
||||
mouseIsOver = true;
|
||||
t.globalBind('mousemove.dur', function(e) {
|
||||
handleMouseMove(e);
|
||||
});
|
||||
if (!mejs.MediaFeatures.hasTouch) {
|
||||
timefloat.show();
|
||||
}
|
||||
})
|
||||
.bind('mouseleave',function(e) {
|
||||
mouseIsOver = false;
|
||||
if (!mouseIsDown) {
|
||||
t.globalUnbind('.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 = Math.round(t.total.width() * t.media.currentTime / t.media.duration),
|
||||
handlePos = newWidth - Math.round(t.handle.outerWidth(true) / 2);
|
||||
|
||||
t.current.width(newWidth);
|
||||
t.handle.css('left', handlePos);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
})(mejs.$);
|
||||
@@ -0,0 +1,87 @@
|
||||
// Source Chooser Plugin
|
||||
(function($) {
|
||||
|
||||
$.extend(mejs.MepDefaults, {
|
||||
sourcechooserText: 'Source Chooser'
|
||||
});
|
||||
|
||||
$.extend(MediaElementPlayer.prototype, {
|
||||
buildsourcechooser: function(player, controls, layers, media) {
|
||||
|
||||
var t = this;
|
||||
|
||||
player.sourcechooserButton =
|
||||
$('<div class="mejs-button mejs-sourcechooser-button">'+
|
||||
'<button type="button" aria-controls="' + t.id + '" title="' + t.options.sourcechooserText + '" aria-label="' + t.options.sourcechooserText + '"></button>'+
|
||||
'<div class="mejs-sourcechooser-selector">'+
|
||||
'<ul>'+
|
||||
'</ul>'+
|
||||
'</div>'+
|
||||
'</div>')
|
||||
.appendTo(controls)
|
||||
|
||||
// hover
|
||||
.hover(function() {
|
||||
$(this).find('.mejs-sourcechooser-selector').css('visibility','visible');
|
||||
}, function() {
|
||||
$(this).find('.mejs-sourcechooser-selector').css('visibility','hidden');
|
||||
})
|
||||
|
||||
// handle clicks to the language radio buttons
|
||||
.delegate('input[type=radio]', 'click', function() {
|
||||
src = this.value;
|
||||
|
||||
if (media.currentSrc != src) {
|
||||
currentTime = media.currentTime;
|
||||
paused = media.paused;
|
||||
media.setSrc(src);
|
||||
media.load();
|
||||
media.addEventListener('loadedmetadata', function(e){
|
||||
this.currentTime = currentTime;
|
||||
}, true);
|
||||
media.addEventListener('canplay', function(e){
|
||||
if (!paused) {
|
||||
this.play();
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
});
|
||||
|
||||
// add to list
|
||||
for (i in media.children) {
|
||||
src = media.children[i];
|
||||
if (src.nodeName === 'SOURCE' && (media.canPlayType(src.type) == 'probably' || media.canPlayType(src.type) == 'maybe')) {
|
||||
player.addSourceButton(src.src, src.title, src.type, media.src == src.src);
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
addSourceButton: function(src, label, type, isCurrent) {
|
||||
var t = this;
|
||||
if (label === '' || label == undefined) {
|
||||
label = src;
|
||||
}
|
||||
type = type.split('/')[1];
|
||||
|
||||
t.sourcechooserButton.find('ul').append(
|
||||
$('<li>'+
|
||||
'<input type="radio" name="' + t.id + '_sourcechooser" id="' + t.id + '_sourcechooser_' + label + type + '" value="' + src + '" ' + (isCurrent ? 'checked="checked"' : '') + ' />'+
|
||||
'<label for="' + t.id + '_sourcechooser_' + label + type + '">' + label + ' (' + type + ')</label>'+
|
||||
'</li>')
|
||||
);
|
||||
|
||||
t.adjustSourcechooserBox();
|
||||
|
||||
},
|
||||
|
||||
adjustSourcechooserBox: function() {
|
||||
var t = this;
|
||||
// adjust the size of the outer box
|
||||
t.sourcechooserButton.find('.mejs-sourcechooser-selector').height(
|
||||
t.sourcechooserButton.find('.mejs-sourcechooser-selector ul').outerHeight(true)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
})(mejs.$);
|
||||
@@ -0,0 +1,11 @@
|
||||
(function($) {
|
||||
|
||||
MediaElementPlayer.prototype.buildspeed = function(player, controls, layers, media) {
|
||||
if (!player.isVideo)
|
||||
return;
|
||||
|
||||
// add speed controls
|
||||
}
|
||||
|
||||
|
||||
})(mejs.$);
|
||||
@@ -0,0 +1,33 @@
|
||||
(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 + '" aria-label="' + t.options.stopText + '"></button>' +
|
||||
'</div>')
|
||||
.appendTo(controls)
|
||||
.click(function() {
|
||||
if (!media.paused) {
|
||||
media.pause();
|
||||
}
|
||||
if (media.currentTime > 0) {
|
||||
media.setCurrentTime(0);
|
||||
media.pause();
|
||||
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.$);
|
||||
@@ -0,0 +1,84 @@
|
||||
(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;
|
||||
|
||||
//Toggle the long video class if the video is longer than an hour.
|
||||
t.container.toggleClass("mejs-long-video", t.media.duration > 3600);
|
||||
|
||||
if (t.durationD && (t.options.duration > 0 || t.media.duration)) {
|
||||
t.durationD.html(mejs.Utility.secondsToTimeCode(t.options.duration > 0 ? t.options.duration : t.media.duration, t.options.alwaysShowHours, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
})(mejs.$);
|
||||
@@ -0,0 +1,678 @@
|
||||
(function($) {
|
||||
|
||||
// add extra default options
|
||||
$.extend(mejs.MepDefaults, {
|
||||
// this will automatically turn on a <track>
|
||||
startLanguage: '',
|
||||
|
||||
tracksText: mejs.i18n.t('Captions/Subtitles'),
|
||||
|
||||
// option to remove the [cc] button when no <track kind="subtitles"> are present
|
||||
hideCaptionsButtonWhenEmpty: true,
|
||||
|
||||
// If true and we only have one track, change captions to popup
|
||||
toggleCaptionsButtonWhenOnlyOne: false,
|
||||
|
||||
// #id or .class
|
||||
slidesSelector: ''
|
||||
});
|
||||
|
||||
$.extend(MediaElementPlayer.prototype, {
|
||||
|
||||
hasChapters: false,
|
||||
|
||||
buildtracks: function(player, controls, layers, media) {
|
||||
if (player.tracks.length == 0)
|
||||
return;
|
||||
|
||||
var t = this,
|
||||
i,
|
||||
options = '';
|
||||
|
||||
if (t.domNode.textTracks) { // if browser will do native captions, prefer mejs captions, loop through tracks and hide
|
||||
for (var i = t.domNode.textTracks.length - 1; i >= 0; i--) {
|
||||
t.domNode.textTracks[i].mode = "hidden";
|
||||
}
|
||||
}
|
||||
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 mejs-captions-position-hover"><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 + '" aria-label="' + 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">' + mejs.i18n.t('None') +'</label>'+
|
||||
'</li>' +
|
||||
'</ul>'+
|
||||
'</div>'+
|
||||
'</div>')
|
||||
.appendTo(controls);
|
||||
|
||||
|
||||
var subtitleCount = 0;
|
||||
for (i=0; i<player.tracks.length; i++) {
|
||||
if (player.tracks[i].kind == 'subtitles') {
|
||||
subtitleCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// if only one language then just make the button a toggle
|
||||
if (t.options.toggleCaptionsButtonWhenOnlyOne && subtitleCount == 1){
|
||||
// click
|
||||
player.captionsButton.on('click',function() {
|
||||
if (player.selectedTrack == null) {
|
||||
var lang = player.tracks[0].srclang;
|
||||
} else {
|
||||
var lang = 'none';
|
||||
}
|
||||
player.setTrack(lang);
|
||||
});
|
||||
} else {
|
||||
// hover
|
||||
player.captionsButton.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
|
||||
.on('click','input[type=radio]',function() {
|
||||
lang = this.value;
|
||||
player.setTrack(lang);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
if (!player.options.alwaysShowControls) {
|
||||
// move with controls
|
||||
player.container
|
||||
.bind('controlsshown', function () {
|
||||
// push captions above controls
|
||||
player.container.find('.mejs-captions-position').addClass('mejs-captions-position-hover');
|
||||
|
||||
})
|
||||
.bind('controlshidden', 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);
|
||||
}
|
||||
}
|
||||
|
||||
// start loading tracks
|
||||
player.loadNextTrack();
|
||||
|
||||
|
||||
media.addEventListener('timeupdate',function(e) {
|
||||
player.displayCaptions();
|
||||
}, false);
|
||||
|
||||
if (player.options.slidesSelector != '') {
|
||||
player.slidesContainer = $(player.options.slidesSelector);
|
||||
|
||||
media.addEventListener('timeupdate',function(e) {
|
||||
player.displaySlides();
|
||||
}, 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');
|
||||
}
|
||||
},
|
||||
|
||||
setTrack: function(lang){
|
||||
|
||||
var t = this,
|
||||
i;
|
||||
|
||||
if (lang == 'none') {
|
||||
t.selectedTrack = null;
|
||||
t.captionsButton.removeClass('mejs-captions-enabled');
|
||||
} else {
|
||||
for (i=0; i<t.tracks.length; i++) {
|
||||
if (t.tracks[i].srclang == lang) {
|
||||
if (t.selectedTrack == null)
|
||||
t.captionsButton.addClass('mejs-captions-enabled');
|
||||
t.selectedTrack = t.tracks[i];
|
||||
t.captions.attr('lang', t.selectedTrack.srclang);
|
||||
t.displayCaptions();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
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;
|
||||
|
||||
t.checkForTracks();
|
||||
}
|
||||
},
|
||||
|
||||
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.addEventListener('play', function(e) {
|
||||
if (t.media.duration > 0) {
|
||||
t.displayChapters(track);
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
if (track.kind == 'slides') {
|
||||
t.setupSlides(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)
|
||||
);
|
||||
},
|
||||
|
||||
checkForTracks: function() {
|
||||
var
|
||||
t = this,
|
||||
hasSubtitles = false;
|
||||
|
||||
// check if any subtitles
|
||||
if (t.options.hideCaptionsButtonWhenEmpty) {
|
||||
for (i=0; i<t.tracks.length; i++) {
|
||||
if (t.tracks[i].kind == 'subtitles') {
|
||||
hasSubtitles = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasSubtitles) {
|
||||
t.captionsButton.hide();
|
||||
t.setControlsSize();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
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();
|
||||
}
|
||||
},
|
||||
|
||||
setupSlides: function(track) {
|
||||
var t = this;
|
||||
|
||||
t.slides = track;
|
||||
t.slides.entries.imgs = [t.slides.entries.text.length];
|
||||
t.showSlide(0);
|
||||
|
||||
},
|
||||
|
||||
showSlide: function(index) {
|
||||
if (typeof this.tracks == 'undefined' || typeof this.slidesContainer == 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
var t = this,
|
||||
url = t.slides.entries.text[index],
|
||||
img = t.slides.entries.imgs[index];
|
||||
|
||||
if (typeof img == 'undefined' || typeof img.fadeIn == 'undefined') {
|
||||
|
||||
t.slides.entries.imgs[index] = img = $('<img src="' + url + '">')
|
||||
.on('load', function() {
|
||||
img.appendTo(t.slidesContainer)
|
||||
.hide()
|
||||
.fadeIn()
|
||||
.siblings(':visible')
|
||||
.fadeOut();
|
||||
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
if (!img.is(':visible') && !img.is(':animated')) {
|
||||
|
||||
//console.log('showing existing slide');
|
||||
|
||||
img.fadeIn()
|
||||
.siblings(':visible')
|
||||
.fadeOut();
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
displaySlides: function() {
|
||||
|
||||
if (typeof this.slides == 'undefined')
|
||||
return;
|
||||
|
||||
var
|
||||
t = this,
|
||||
slides = t.slides,
|
||||
i;
|
||||
|
||||
for (i=0; i<slides.entries.times.length; i++) {
|
||||
if (t.media.currentTime >= slides.entries.times[i].start && t.media.currentTime <= slides.entries.times[i].stop){
|
||||
|
||||
t.showSlide(i);
|
||||
|
||||
return; // exit out if one is visible;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
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) + '–' + 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.$);
|
||||
@@ -0,0 +1,10 @@
|
||||
(function($) {
|
||||
|
||||
MediaElementPlayer.prototype.buildvisualcontrols = function(player, controls, layers, media) {
|
||||
if (!player.isVideo)
|
||||
return;
|
||||
|
||||
// add visual controls (HSV)
|
||||
}
|
||||
|
||||
})(mejs.$);
|
||||
@@ -0,0 +1,225 @@
|
||||
(function($) {
|
||||
|
||||
$.extend(mejs.MepDefaults, {
|
||||
muteText: mejs.i18n.t('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 + '" aria-label="' + 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 + '" aria-label="' + 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', Math.round(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', Math.round(totalPosition.left + newLeft - (volumeHandle.width() / 2)));
|
||||
|
||||
// rezize the current part of the volume bar
|
||||
volumeCurrent.width( Math.round(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);
|
||||
t.globalBind('mousemove.vol', function(e) {
|
||||
handleVolumeMove(e);
|
||||
});
|
||||
t.globalBind('mouseup.vol', function () {
|
||||
mouseIsDown = false;
|
||||
t.globalUnbind('.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);
|
||||
|
||||
// mutes the media and sets the volume icon muted if the initial volume is set to 0
|
||||
if (player.options.startVolume === 0) {
|
||||
media.setMuted(true);
|
||||
}
|
||||
|
||||
// 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.$);
|
||||
@@ -0,0 +1,11 @@
|
||||
/*!
|
||||
* 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-2013, John Dyer (http://j.hn/)
|
||||
* License: MIT
|
||||
*
|
||||
*/
|
||||
@@ -0,0 +1,5 @@
|
||||
if (typeof jQuery != 'undefined') {
|
||||
mejs.$ = jQuery;
|
||||
} else if (typeof ender != 'undefined') {
|
||||
mejs.$ = ender;
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"name": "mediaelement",
|
||||
"filename": "js/mediaelement.min.js",
|
||||
"version": "2.11.3",
|
||||
"version": "2.13.1",
|
||||
"version": "2.13.2",
|
||||
"description": "HTML5 audio and video players in pure HTML and CSS. MediaElementPlayer.js uses the same HTML/CSS for all players.",
|
||||
"homepage": "http://mediaelementjs.com/",
|
||||
"keywords": [
|
||||
|
||||