Changeset 1973
- Timestamp:
- 08/23/11 04:49:08 (21 months ago)
- Location:
- plugins/captions
- Files:
-
- 6 added
- 3 deleted
- 24 edited
-
assets/active.png (modified) (previous)
-
assets/back.png (modified) (previous)
-
assets/divider.png (modified) (previous)
-
assets/down.png (deleted)
-
assets/is_off.png (added)
-
assets/is_on.png (added)
-
assets/not_set.png (added)
-
assets/up.png (deleted)
-
captions.js (modified) (1 diff)
-
captions.swf (modified) (previous)
-
doc/guide.html (modified) (4 diffs)
-
src/as/com/longtailvideo/plugins/captions/Captions.as (modified) (7 diffs)
-
src/as/com/longtailvideo/plugins/captions/ISO639.as (modified) (1 diff)
-
src/as/com/longtailvideo/plugins/captions/Renderer.as (modified) (1 diff)
-
src/as/com/longtailvideo/plugins/captions/Selector.as (modified) (4 diffs)
-
src/as/com/longtailvideo/plugins/captions/SelectorButton.as (modified) (3 diffs)
-
src/as/com/longtailvideo/plugins/captions/SelectorUpDown.as (deleted)
-
src/js/captions.js (modified) (1 diff)
-
src/js/captions.renderer.js (modified) (1 diff)
-
src/js/captions.selector.js (modified) (1 diff)
-
src/js/captions.srt.js (modified) (1 diff)
-
test/assets/bunny-ned.txt (modified) (1 diff)
-
test/assets/malformed.srt (added)
-
test/assets/malformed.xml (added)
-
test/assets/playlist.xml (modified) (1 diff)
-
test/basic.html (modified) (4 diffs)
-
test/compatibility.html (modified) (1 diff)
-
test/errors.html (added)
-
test/index.html (modified) (1 diff)
-
test/modes.html (modified) (1 diff)
-
test/multiple.html (modified) (1 diff)
-
test/options.html (modified) (2 diffs)
-
test/playlist.html (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
plugins/captions/captions.js
r1964 r1973 1 (function(a){var b=function( g,e,d){function f(){if(g.getRenderingMode()=="flash"){return}}g.onReady(f);this.resize=function(i,h){if(g.getRenderingMode()=="flash"){return}};function c(h,i){for(var j in i){h.style[j]=i[j]}}};a().registerPlugin("captions",b,"./captions.swf")})(jwplayer);1 (function(a){var b=function(d,h,r){var o={back:false,color:"#FFFFFF",fontFamily:"Arial,sans-serif",fontSize:15,fontStyle:"normal",fontWeight:"normal",state:true,textDecoration:"none"};var m=["data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA6ZJREFUeNrsWM9LVFEUfm8cU7NsxkwU+zGhRQWB1aY29RYtXIVRUO1mKW1qE/inCG2ENq0qCMJFCxcupBYFQQxSYog1CPkDC8ccnb5D37XD5YmPeU9fxD3wcd67c+be85177r3nPs9z4sSJEydOnPw/4kcxqtVqYrcPaCZagENAm2proo3oLNBIbcsvoEq9RlSIH8Ay8BNYZdua7/ubO/mYjUj4HtBDR7NRAxBTNoB1YA54khSRDqB1m98kiiVgnoML2aNAL2fKdu4LMM2IS0DywGngiGXbQOSjOJiNGbUp4DmmfjUkHQ9D3SQpj2nyDLZTIbavoa4BQb2OZGKQWAFeGhJwJgM0cz15aP8O9Qow+T2uScCuCcjStgaM4/FDGkQ+YfAV9X4deASc3dpJfP8rVJmv04pEN9QD4JbdZxpEFq3348zpcyFrqMoZNHIM2C/rCKTaVPtqvc7EWSOb22zlB+FcJ/uucsFXLfuMWtA9sG/h7+1pENlOTgD3Q9ZTmAiRO0kMmkmQwF6cLXtCJFXS2V1wbgF4wyDJAXiRpUxo9QNMsizxeCheSo2IOTsoy9h2J9VvPSGL2FdE3sF+nrYn6yUSJ7Ua1HlRo1OmKLTHyFhj1VTJUk0i5eLMSIf1/pH9vbXa8ySdU+fEZxaDcwjCgrJtS4NIH1Kh3TgCPQE1YaVcL6tmkVPAN9pKKj22bGXGzqexa8khNggH8mFrBpBSZVA1X0XbhW3WmNxtbrNiTmXXkrJkCI7MsoyvMoW6mXq+NdYN2F6BnmXpIqd+p7rr7Pr2u8jaqFEvcorcCPuIKFt0JxH1YrWY5FU3Q4dbGMUDjHyrddU119us2ql81lFmZ9tQu9V6UlddJ06cOIlVROaAwQT6OQNcTvxkR6ddAqtNvpwURKvmHBHWR5i9IV+wzLtCvo3VfyBigCI7lH1dyLzA3l6SiLEMKbP9Kdpn8Fzk/wJ+5tkKBNRdYAkQMqNiD93Pb1pLQgh6lIEI+L8Z9ht7iovilJpu4+iQiSKjPKSeiyH9BCbl2E+OM/TQzJCkEjCg7IPEZoRiIlLRU28ixch27dDHe5kt2A17fz6zlpk+Ev1htNtj7VnRWJFIgkSFEa3sZA+MqLSRyEvqldHHiFlDaXx8KLGUL3CtlNRvzcx3LQO0M6QrIFCmbcB+JCX1TpWLQi4qkbKKdsX7+xl0jM8B9ZiylwXdb/Uzxv8H6t2zFndJbRAlthfcoebEiRMn/6T8FmAAOmqqRlH6QggAAAAASUVORK5CYII=","data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA09JREFUeNrsmEtIVFEYx+fOjI1WNmkUPUxDjR4USZIUFANBtigoqn1R0Np9C1u2y0XQKrCNKwmJoLDAhOhBhEG1U9Qg7YHNlJaPKaf/B/+Rj8O9Oc29M2N1Pvhx7jn3u/ee/3l+54ZC1qxZs2bNmrV/x5xcnDKZTBjJCrAaVIFqUAs2MR8Hq8BKpuVgOVP9jQz4BqbBFPhKvoAk+ADeMk2SScdxfixWx2iOgm+DFoqpyLUBfNoc+A6eg9aghGwHaz3uvQc94DU/Lr2yHxxlT2lLg37wAHwGEVAPjoMdhu8yUh9Y02BoDWbc7Q6o9nhmK3iqfJPgmNfQBe0e3xgstJAxsEH5REAcOKqsGaTp32a8sxKUG2Vd+QoJ+9B3F5NwXOWvgE/g9MJK4jgvkLxk9r6q8F4kw6DLeOe9fCvjR8iwkT8IysAZo1xWoBkwpsoOgDXgCETVqPKJfCsT9SEkbeQjTDeicruQxihAluxZ8NPluzKZ93GeyRLbWAohXkvwIfDKKBv38BUht4KYx+FQcOYUyPf/EhItgJAhcI3vlg3yAtjs4SshSwfDErneCS4WW0hGLaeOqtwolt0Oda/FZRJnfWUBuAH/N/Q9nK8QP0MrpvYLETXP7JTLalZmNNq8Wvlmghhyfnpkm5HvZrR73ShvoJA6xlfZzVGCwWdohCHlW1PQMNQjRJkADYs816r8Ly3iKyFObyliLbFHoN7F3wGnwDvlOw3Oe7y/FnT7CRpzPVgNcoi42SR4zE1wlkOomUMv7LJAyMR+wvBfwvzdsrsz/HezIQy/xqCE9PJgVcHduBi2cLCCkNaghER5hK0i69ny65iXeKqSJ8gYBUe4mIQZR2VXtjn23AwrKkfdFJEAcxR8/NOjrjVr1gq3Se6RM3pA70mY18UUclU+7PMdJ/h3pU9fl7qHEqDuN/fj9ImrMvkF1G5eF7vifdmKgQHmk26VMVo+yecSKgzpU9ftpRKSoJC41xjn/YTquYGge8T3URe7br/amS97uDXRL+vftFTP7OfAFv6M63G5n8rODaapJScEFTvLyjepnjFN7ndyeHV6iC3Zzwdp/RSGyk1UUHqjjSJOuvi2ERl6D/nDQWxE+YzY3dmaNWvW/jr7JcAAj0e1BA7EkwQAAAAASUVORK5CYII=","data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA0tJREFUeNrsmM9LVFEUx30zY2pl/oiiH6YxGv2gUJKkoFCCbFFgVH9AFLSefQtdtpxF0CqalSuJiKCwwIToBxEK1U4Rg7QfmFNajlpO3wPfkcPlPZ3mvXHM7oEPZ+6d89475917zz33FRVZsWLFihUrVtaOONkYpdPpENQGUAmqQDWoBTvZrgCbwEbqUrCeWj8jDX6AGTANvpNvYBJ8Au+pJ8mU4zi/lvMxkmXA90ALgynL9gX4lDnwE7wC7UEFsg9s8fjvI7gL3vLhMipHwWmOlJZ50A8eg68gDKLgLNhv2K4j0cBeDabWUNpd7oNqj2v2gBfKdhKc8Zq6oNPjGUP5DmQMbFc2YVABHNXXDOZpHzPuWQ5Kjb7uXAMJ+YjvARbhuGpfB1/AhcVM4jivoQbZfKQcPgw1ArqNez7M1Rk/gYwY7eOgGFw0+iUDpcCY6jsGNoNTCKpG9U/k6kzERyDzRjtMvQPOHYQuYQCSsmfBb5fnymI+wnUmKbahEIF4peAT4I3RN+5hK4HcCWIdh4qCEydPtv9XIJE8BDIMbvDeskFeAbs8bKVkibMskd8HwNWVDiSt0qmjnBtF2o2r/1pcFnHGVhLALdi/o+3JXAPxM7VK1H4hQS2wOe2SzYqNl7agMl8qiCnnZ0T2Gu0eVrs3jf56BlLH+iqzOUox+BIvYVjZ1uS1DPUoUSZA/TLXtSv7a8vYSonTW4haS+QpiLrYO+A8+KBsZ8Blj/vXgh4/RWO2B6shThE3mQLPuAnOcgo1c+qFXBKELOznLP+lzD8kuzvLfzcZxvRrCCqQXh6syrgbr4QsHqwQSHtQgUR4hK0i2/jmt7It9VQ5T5AlDDjMZBJiHZXJbHMcuRQdlaNukkiBOQo+/+1R14oVK/nbJBvljL5a/PFTa10Cu9fa6MjXk9alRmgpG45uY6Gc76Nj4sQI2yKtLrYd/K7VR92q7jGg+jsKGYh8WLutHK5zsR1Qzss1A+oeneravkIedROgTd4o9DkPmybszv08u4huUv89oU4W+syepGNtLFXibjaZtUGdXE1ZKyNxjkqlqplMkY/cCU6vBNurJpBBOh2j7mJ/zMU2Rvsu6phxj8zIDtod2ooVK1b+KfkjwAC9JXx/mwsoAgAAAABJRU5ErkJggg=="];var v;var x;var i;var f=[];var u;function k(z,C){z="jwplayercaptions"+z;if(C!==undefined){var D=z+"="+C+"; expires=Wed, 1 Jan 2020 00:00:00 UTC; path=/";document.cookie=D}else{var B=document.cookie.split(";");for(var A=0;A<B.length;A++){var D=B[A];while(D.charAt(0)==" "){D=D.substring(1,D.length)}if(D.indexOf(z)==0){return D.substring(z.length+1,D.length)}}}return null}var w=function(){if(f.length>1){x.show();try{d.getPlugin("display").hide();d.getPlugin("dock").hide()}catch(z){}}else{if(f.length==1){o.state=!o.state;k("state",o.state);e()}}};function p(z){console.log("CAPTIONS("+z+")")}function n(z){u="idle";e()}function q(z){i=0;f=[];v.update(0);x.hide();try{d.getPlugin("display").show();d.getPlugin("dock").show()}catch(E){}var G=d.getPlaylist()[z.index];if(G["captions.files"]){var I=false;var A=G["captions.files"].split(",");if(G["captions.labels"]){var D=G["captions.labels"].split(",")}for(var C=0;C<A.length;C++){var F={file:A[C]};if(D&&D[C]){F.label=D[C]}else{F.label=A[C].substring(A[C].lastIndexOf("/")+1,A[C].indexOf(".")-1)}if(o.label==F.label){I=true;i=f.length;y(F.file)}f.push(F)}if(I==false){o.state=false}var H=[{label:"(Off)"}];for(var B=0;B<f.length;B++){H.push({label:f[B].label})}if(o.state){x.populate(H,i+1)}else{x.populate(H,0)}}else{if(G["captions.file"]){f.push({file:G["captions.file"]});y(f[0].file)}}e()}function y(A){var z=new a.captions.srt(t,p);z.load(A)}function t(z){v.populate(z);f[i].data=z;e()}function j(z){u="playing";e()}function s(z){if(o.file){d.getPlaylist()[0]["captions.file"]=o.file}if(o.files){d.getPlaylist()[0]["captions.files"]=o.files}if(o.labels){d.getPlaylist()[0]["captions.labels"]=o.labels}}function e(){if(!f.length){d.getPlugin("dock").setButton("captions",w,m[0]);v.hide()}else{if(o.state){d.getPlugin("dock").setButton("captions",w,m[2]);if(u=="playing"){v.show()}else{v.hide()}}else{d.getPlugin("dock").setButton("captions",w,m[1]);v.hide()}}}this.resize=function(A,z){if(d.getRenderingMode()=="flash"){return}v.resize(A,z);x.resize(A,z)};function g(){if(d.getRenderingMode()=="flash"){return}d.onPlaylist(s);d.onPlaylistItem(q);d.onIdle(n);d.onPlay(j);d.onTime(c);if(k("state")!==null){if(k("state")=="true"){o.state=true}else{o.state=false}}if(k("label")!==null){o.label=k("label")}for(var z in h){o[z]=h[z]}v=new a.captions.renderer(o,r);x=new a.captions.selector(l,r);e()}d.onReady(g);function l(A){x.hide();try{d.getPlugin("display").show();d.getPlugin("dock").show()}catch(z){}if(A>0){o.state=true;i=A-1;o.label=f[i].label}else{_config.state=false}k("label",o.label);k("state",o.state);if(f[i].data){v.populate(f[i].data)}else{y(f[i].file)}e()}function c(z){v.update(z.position)}};a.captions={};a().registerPlugin("captions",b,"./captions.swf")})(jwplayer);(function(a){a.captions.renderer=function(k,e){var j;var d;var h;var g;this.hide=function(){b({display:"none"})};this.populate=function(l){g=-1;j=l;c()};function i(l){d.innerHTML=l}this.resize=function(m,l){};function c(){var m=-1;for(var l=0;l<j.length;l++){if(j[l]["begin"]<=h&&(l==j.length-1||j[l+1]["begin"]>=h)){m=l;break}}if(m==-1){i("")}else{if(m!=g){g=m;i(j[l]["text"])}}}function f(){d=document.createElement("p");e.appendChild(d);b({color:k.color,fontFamily:k.fontFamily,fontSize:k.fontSize+"px",fontStyle:k.fontStyle,fontWeight:k.fontWeight,lineHeight:Math.round(k.fontSize*1.4)+"px",textAlign:"center",textDecoration:k.textDecoration});if(k.back){b({textShadow:"#000 1px 1px 0"})}else{b({background:"#000"})}}f();this.show=function(){b({display:"block"})};function b(l){for(var m in l){d.style[m]=l[m]}}this.update=function(l){h=l;if(j){c()}}}})(jwplayer);(function(a){a.captions.selector=function(d,c){this.hide=function(){};this.populate=function(e,f){};this.resize=function(f,e){};this.show=function(){};function b(e,f){for(var g in f){e.style[g]=f[g]}}}})(jwplayer);(function(a){a.captions.srt=function(g,b){var d;var c;function h(k){if(k==0){b("Crossdomain loading denied: "+c)}else{if(k==404){b("SRT File not found: "+c)}else{b("Error "+k+" loading SRT file: "+c)}}}this.load=function(l){c=l;try{d.open("GET",l,true);d.send(null)}catch(k){b("Error loading SRT File: "+l)}};function f(n){_captions=[{begin:0,text:""}];n=n.replace(/^\s+/,"").replace(/\s+$/,"");var m=n.split("\r\n\r\n");if(m.length==1){m=n.split("\n\n")}for(var k=0;k<m.length;k++){var l=j(m[k]);if(l.begin&&l.text){_captions.push(l);if(l.end){_captions.push({begin:l.end,text:""});delete l.end}}}if(_captions.length>1){g(_captions)}else{b("Invalid SRT file: "+c)}}function j(o){var n={};var p=o.split("\r\n");if(p.length==1){p=o.split("\n")}try{var l=p[1].indexOf(" --> ");if(l>0){n.begin=i(p[1].substr(0,l));n.end=i(p[1].substr(l+5))}if(p[2]){n.text=p[2];for(var m=3;m<p.length;m++){n.text+="<br/>"+p[m]}}}catch(k){}return n}function i(k){k=k.replace(",",".");var m=k.split(":");var l=0;if(k.substr(-1)=="s"){l=Number(k.substr(0,k.length-1))}else{if(k.substr(-1)=="m"){l=Number(k.substr(0,k.length-1))*60}else{if(k.substr(-1)=="h"){l=Number(k.substr(0,k.length-1))*3600}else{if(m.length>1){l=Number(m[m.length-1]);l+=Number(m[m.length-2])*60;if(m.length==3){l+=Number(m[m.length-3])*3600}}else{l=Number(k)}}}}return l}function e(){d=new XMLHttpRequest();d.onreadystatechange=function(){if(d.readyState===4){if(d.status===200){f(d.responseText)}else{h(d.status)}}}}e()}})(jwplayer); -
plugins/captions/doc/guide.html
r1964 r1973 26 26 <h2>Introduction</h2> 27 27 28 <p>The Captions plugin for JW Player supports the display of closed captions or subtitles at the bottom of a video. More creative use cases are karaoke, or the displaying of timed comments with the video.Captions can be shown or hidden with a toggle:</p>28 <p>The Captions plugin for JW Player supports the display of closed captions or subtitles at the bottom of a video. Captions can be shown or hidden with a toggle:</p> 29 29 30 30 <p><img src="assets/captions_example.png" alt="A screenshot of example captions implementation" style="margin-left:15px"/></p> … … 46 46 <dd>Location of the captions file to display. Should be the URL to a valid <a href="#dfxp">DFXP</a> or <a href="#srt">SRT</a> captions file. If your captions are embedded in your MP4 videos, or if you use a playlist, this option is not needed.</dd> 47 47 <dt><b>state</b> (<em>true</em>)</dt> 48 <dd>Describes whether to show the captions on startup or not. The default is <b>true</b> (captions are shown). When changed, the value is saved in a cookie, so users won't have to disable the captions on every video again if they don't want them.</dd>48 <dd>Describes whether to show the captions on startup or not. The default is <b>true</b> (captions are shown). When a viewer changes the state, the value is saved in a cookie, so users won't have to disable the captions on every video again if they don't want them.</dd> 49 49 </dl> 50 50 … … 159 159 <dd>Set this value to a second comma-separated list, defining the labels for each language that should pop up in the selection menu (e.g. <em>English,Deutsch,Francais</em>). The amount and order of these labels should be the same as the amount and order of entries in the <b>files</b> option.</dd> 160 160 </dl> 161 162 <p>When a viewer changes the captions track, the value is saved in a cookie. That way the viewer won't have to re-set the track with every new video or page reload.<p> 161 163 162 164 <h3>Example</h3> … … 306 308 </ul> 307 309 <ul> 308 <li>Enhanced support for dock button language shortcode in multitrack setups. The f irst three characters of labels are now used.</li>310 <li>Enhanced support for dock button language shortcode in multitrack setups. The full label is simply shown.</li> 309 311 <li>Made captions aware of controlbar in the "over" state. For player 5.7+, the captions will now scroll up if the controlbar shows and scroll down again if the controlbar hides.</li> 310 312 <li>Added a timed transition to showing/hiding of the language selector.</li> 311 313 <li>Added a close button to the language selector menu.</li> 314 <li>Added support for displaying filenames in language selector if labels are not shown.</li> 315 </ul> 316 <ul> 317 <li>Fixed an issue with language selector tabbing that required two tabs for advancing one entry.</li> 312 318 <li>Fixed an issue with OVA advertising that caused displaying captions on the preroll.</li> 313 319 </ul> -
plugins/captions/src/as/com/longtailvideo/plugins/captions/Captions.as
r1964 r1973 29 29 private var _config:Object = { 30 30 back: false, 31 code: undefined,31 label: undefined, 32 32 file: undefined, 33 33 state: true … … 189 189 } 190 190 for(var i:Number = 0; i < files.length; i++) { 191 var entry:Object = { 192 file: files[i], 193 code: files[i].substr(files[i].indexOf('.')-3,3) 194 }; 191 var entry:Object = { file: files[i] }; 195 192 // Set label. 196 193 if(labels && labels[i]) { 197 194 entry.label = labels[i]; 198 entry.code = labels[i].substr(0,3).toLowerCase(); 199 } else { 200 entry.label = ISO639.label(entry.code); 201 } 202 if(_config.code == entry.code) { 195 } else { 196 var slash:Number = files[i].lastIndexOf('/'); 197 var dot:Number = files[i].indexOf('.'); 198 entry.label = files[i].substr(slash+1,1).toUpperCase()+files[i].substr(slash+2,dot-slash-2); 199 } 200 if(_config.label == entry.label) { 203 201 _track = _tracks.length; 204 202 found = true; … … 256 254 for(var i:Number = 0; i < info.length; i++) { 257 255 if(info[i].sampledescription[0].sampletype == 'tx3g') { 258 if(_config. code == info[i].language) {256 if(_config.label == ISO639.label(info[i].language)) { 259 257 _track = _tracks.length; 260 258 found = true; 261 259 } 262 260 _tracks.push({ 263 code: info[i].language,264 261 data: undefined, 265 262 file: undefined, … … 297 294 /** Populate the selector. **/ 298 295 private function _populateSelector():void { 299 var options:Array = new Array({label:' Captions Off'});296 var options:Array = new Array({label:'(Off)'}); 300 297 for(var j:Number=0; j<_tracks.length; j++) { 301 298 options.push({label:_tracks[j].label}); … … 336 333 _button.field.alpha = 1; 337 334 if(_tracks.length > 1) { 338 _button.field.text = '('+_tracks[_track].code+')';335 _button.field.text = _tracks[_track].label.toLowerCase(); 339 336 } else { 340 337 _button.field.text = 'is on'; … … 354 351 // Resize the captions, a bit smaller in fullscreen 355 352 if(_player.config.fullscreen) { 356 _renderer.x = width / 6;357 _renderer.width = width * 2/3;353 _renderer.x = width / 8; 354 _renderer.width = width * 3 / 4; 358 355 } else { 359 356 _renderer.x = width / 24; … … 381 378 (_player.controls.dock as Object).show(); 382 379 } catch (error:Error) {} 383 // Set and cookie state/ code380 // Set and cookie state/label 384 381 if(index > 0) { 385 382 _config.state = true; 386 383 _track = index - 1; 387 _config. code = _tracks[_track].code;384 _config.label = _tracks[_track].label; 388 385 } else { 389 386 _config.state = false; 390 387 } 391 388 _cookie.data['captions.state'] = _config.state; 392 _cookie.data['captions. code'] = _config.code;389 _cookie.data['captions.label'] = _config.label; 393 390 _cookie.flush(); 394 391 // Update UI -
plugins/captions/src/as/com/longtailvideo/plugins/captions/ISO639.as
r1813 r1973 27 27 fin: 'Finnish', 28 28 fra: 'Français', 29 fre: 'Fr ançais',29 fre: 'French', 30 30 geo: 'Georgian', 31 31 ger: 'Deutsch', -
plugins/captions/src/as/com/longtailvideo/plugins/captions/Renderer.as
r1964 r1973 126 126 public function setPosition(position:Number):void { 127 127 _position = position; 128 if(_captions) { 128 if(_captions) { 129 129 _selectCaption(); 130 130 } -
plugins/captions/src/as/com/longtailvideo/plugins/captions/Selector.as
r1964 r1973 31 31 /** Function to call when a selection is made. **/ 32 32 private var _callback:Function; 33 /** Reference to the page down button. **/34 private var _down:SelectorUpDown;35 /** Offset of the visible entries. **/36 private var _offset:Number;37 33 /** List with options from the selector. **/ 38 34 private var _options:Array; 39 /** Reference to the page up button. **/40 private var _up:SelectorUpDown;41 35 42 36 … … 56 50 addChild(_container); 57 51 _container.buttonMode = true; 58 _down = new SelectorUpDown(false,_downHandler);59 _up = new SelectorUpDown(true,_upHandler);60 52 }; 61 53 … … 76 68 77 69 78 /** The down button was clicked. **/79 private function _downHandler():void {80 _offset++;81 _redraw();82 };83 84 85 /** Return the max number of buttons that fit in the screen. **/86 private function _max():Number {87 return Math.floor(_back.height/27) - 2;88 };89 90 91 70 /** Populate the selector with a number of items. **/ 92 71 public function populate(options:Array,active:Number=0):void { 93 72 _options = options; 94 73 _active = active; 95 // Build all the buttons. 96 for(var i:Number=0; i < _options.length; i++) { 97 _options[i].button = new SelectorButton(_buttonHandler,i,_options[i].label); 98 } 99 _options[_active].button.activate(true); 100 // Redraw the menu. 101 _reoffset(); 102 _redraw(); 103 }; 104 105 106 /** Draw visible portion of the options. **/ 107 private function _redraw():void { 108 var button:SelectorButton; 109 var height:Number = 0; 110 var end:Number; 111 var scroll:Boolean; 112 // clear existing buttons. 74 // Remove existing buttons. 113 75 while(_container.numChildren > 0) { 114 76 _container.removeChildAt(0); 115 77 } 116 // Check if scrollbars are needed and if offset needs correcting. 117 if(_options.length > _max()) { 118 scroll = true; 119 end = _max(); 120 } else { 121 end = _options.length; 122 } 123 if(_offset < 0) { 124 _offset = 0; 125 } else if (scroll && _offset > _options.length - _max()) { 126 _offset = _options.length - _max(); 127 } 128 // Draw prev button if needed. 129 if(scroll) { 130 _container.addChild(_up); 131 _up.y = height; 132 _offset == 0 ? _up.alpha = 0: _up.alpha = 1; 133 height += 26; 134 height = _redrawDivider(height); 135 } 136 // Draw new buttons and dividers 137 for(var i:Number = _offset; i < _offset + end; i++) { 78 // Draw new buttons. 79 for(var i:Number = 0; i<_options.length; i++) { 80 _options[i].button = new SelectorButton(_buttonHandler,i,_options[i].label); 138 81 _container.addChild(_options[i].button); 139 _options[i].button.y = height; 140 height += 26; 141 if(i < _offset + end - 1) { 142 height = _redrawDivider(height); 82 _options[i].button.y = i*25; 83 if(i < _options.length - 1) { 84 var divider:DisplayObject = new DividerRow(); 85 divider.y = i*25 + 24; 86 _container.addChild(divider); 143 87 } 144 88 } 145 //draw next button if needed 146 if(scroll) { 147 height = _redrawDivider(height); 148 _container.addChild(_down); 149 _down.y = height; 150 _offset == _options.length - _max() ? _down.alpha = 0: _down.alpha = 1; 151 height += 26; 152 } 153 // Rescale button list. 154 _container.x = Math.round(_back.width/2 - _container.width/2); 155 _container.y = Math.round(_back.height/2 - height/2); 156 }; 157 158 159 private function _redrawDivider(height:Number):Number { 160 var divider:DisplayObject = new DividerRow(); 161 _container.addChild(divider); 162 divider.y = height; 163 return height + 1; 164 }; 165 166 167 /** If scrolling, set offset such that active track is visible. **/ 168 private function _reoffset():void { 169 if(_active < _max()) { 170 _offset = 0; 171 } else if(_options.length > _max() && _active > _options.length - _max()) { 172 _offset = _options.length - _max(); 173 } else { 174 _offset = _active; 175 } 89 // Set active button and center the list 90 _options[_active].button.activate(true); 91 resize(_back.width,_back.height); 176 92 }; 177 93 … … 183 99 _close.x = width - 50; 184 100 if(_options) { 185 _ reoffset();186 _ redraw();101 _container.x = Math.round(_back.width/2 - _container.width/2); 102 _container.y = Math.round(_back.height/2 - _container.height/2); 187 103 } 188 };189 190 191 /** The up button was clicked. **/192 private function _upHandler():void {193 _offset--;194 _redraw();195 104 }; 196 105 -
plugins/captions/src/as/com/longtailvideo/plugins/captions/SelectorButton.as
r1964 r1973 59 59 _field.height = 20; 60 60 _field.width = 180; 61 _field.y = 3;61 _field.y = 2; 62 62 _field.text = _label; 63 buttonMode = true;64 mouseChildren = false;65 // Insert accessibility options (tabbing / screenreader label).66 var acs:AccessibilityProperties = new AccessibilityProperties();67 acs.name = label;68 accessibilityProperties = acs;69 tabEnabled = true;70 tabChildren = false;71 tabIndex = index + 501;72 63 // Add active indicator (small dot). 73 64 _active = new ActiveIcon(); … … 76 67 _active.visible = false; 77 68 addChild(_active); 78 _active.x = 90 - _field.getLineMetrics(0).width/2 - 26; 69 // Insert accessibility options (tabbing / screenreader label). 70 var acs:AccessibilityProperties = new AccessibilityProperties(); 71 acs.name = label; 72 accessibilityProperties = acs; 73 buttonMode = true; 74 mouseChildren = false; 75 tabEnabled = true; 76 tabChildren = false; 77 tabIndex = index + 501; 79 78 // Set event handlers. 80 79 addEventListener(MouseEvent.CLICK,_clickHandler); … … 86 85 /** (de)activate the button. **/ 87 86 public function activate(state:Boolean):void { 88 if(state) { 87 if(state) { 89 88 _active.visible = true; 90 89 } else { -
plugins/captions/src/js/captions.js
r1964 r1973 2 2 3 3 4 /** Displays closed captions or subtitles on top of the video. **/ 5 var template = function(_player, _options, _div) { 6 7 8 /** Set dock buttons when player is ready. **/ 9 function _setup() { 10 if(_player.getRenderingMode() == 'flash') { return; } 4 /** Displays closed captions or subtitles on top of the video. **/ 5 var template = function(_player, options, _div) { 6 7 8 /** Default configuration options. **/ 9 var _options = { 10 back: false, 11 color: '#FFFFFF', 12 fontFamily: 'Arial,sans-serif', 13 fontSize: 15, 14 fontStyle: 'normal', 15 fontWeight: 'normal', 16 state: true, 17 textDecoration: 'none' 18 }; 19 /** Dock icons. **/ 20 var _icons = [ 21 '../assets/not_set.png', 22 '../assets/is_off.png', 23 '../assets/is_on.png' 24 ]; 25 /** Reference to the text renderer. **/ 26 var _renderer; 27 /** Reference to the language selector. **/ 28 var _selector; 29 /** Currently active captions track. **/ 30 var _track; 31 /** List with all tracks. **/ 32 var _tracks = []; 33 /** Current player state. **/ 34 var _state; 35 36 37 /** Read or write a cookie. **/ 38 function _cookie(name,value) { 39 name = 'jwplayercaptions' + name; 40 if(value !== undefined) { 41 var c = name+'='+value+'; expires=Wed, 1 Jan 2020 00:00:00 UTC; path=/'; 42 document.cookie = c; 43 } else { 44 // http://www.quirksmode.org/js/cookies.html 45 var list = document.cookie.split(';'); 46 for(var i=0; i< list.length; i++) { 47 var c = list[i]; 48 while (c.charAt(0) == ' ') { 49 c = c.substring(1,c.length); 50 } 51 if (c.indexOf(name) == 0) { 52 return c.substring(name.length+1, c.length); 53 } 54 } 55 } 56 return null; 57 }; 58 59 60 /** Dock button was clicked. **/ 61 var dockHandler = function() { 62 if(_tracks.length > 1) { 63 _selector.show(); 64 try { 65 _player.getPlugin('display').hide(); 66 _player.getPlugin('dock').hide(); 67 } catch (error) {} 68 } else if(_tracks.length == 1) { 69 _options.state = !_options.state; 70 _cookie('state',_options.state); 71 _redraw(); 72 } 73 }; 74 75 76 /** Error loading/parsing the captions. **/ 77 function _errorHandler(error) { 78 console.log("CAPTIONS(" + error + ")"); 79 }; 80 81 82 /** Player jumped to idle state. **/ 83 function _idleHandler(event) { 84 _state = 'idle'; 85 _redraw(); 86 }; 87 88 89 /** Listen to playlist item updates. **/ 90 function _itemHandler(event) { 91 _track = 0; 92 _tracks = []; 93 _renderer.update(0); 94 _selector.hide(); 95 try { 96 _player.getPlugin('display').show(); 97 _player.getPlugin('dock').show(); 98 } catch (error) {} 99 var item = _player.getPlaylist()[event.index]; 100 // Load multiple captions 101 if(item['captions.files']) { 102 var found = false; 103 var files = item['captions.files'].split(','); 104 if(item['captions.labels']) { 105 var labels = item['captions.labels'].split(','); 106 } 107 for(var i=0; i<files.length; i++) { 108 var entry = { file: files[i] }; 109 // Set label 110 if(labels && labels[i]) { 111 entry.label = labels[i]; 112 } else { 113 entry.label = files[i].substring(files[i].lastIndexOf('/')+1,files[i].indexOf('.')-1); 114 } 115 // Matched label from cookie. 116 if(_options.label == entry.label) { 117 found = true; 118 _track = _tracks.length; 119 _load(entry.file); 120 } 121 _tracks.push(entry); 122 } 123 if(found == false) { 124 _options.state = false; 125 } 126 // populate selector 127 var options = [{label:'(Off)'}]; 128 for(var j=0; j<_tracks.length; j++) { 129 options.push({label:_tracks[j].label}); 130 } 131 if(_options.state) { 132 _selector.populate(options, _track+1); 133 } else { 134 _selector.populate(options, 0); 135 } 136 // Load single caption 137 } else if(item['captions.file']) { 138 _tracks.push({file:item['captions.file']}); 139 _load(_tracks[0].file); 140 } 141 _redraw(); 142 }; 143 144 145 /** Load captions. **/ 146 function _load(file) { 147 var loader = new jwplayer.captions.srt(_loadHandler,_errorHandler); 148 loader.load(file); 149 }; 150 151 152 /** Captions were loaded. **/ 153 function _loadHandler(data) { 154 _renderer.populate(data); 155 _tracks[_track].data = data; 156 _redraw(); 157 }; 158 159 160 /** Player started playing. **/ 161 function _playHandler(event) { 162 _state = 'playing'; 163 _redraw(); 164 }; 165 166 167 /** Insert global file/files on playlist update. **/ 168 function _playlistHandler(event) { 169 if(_options.file) { 170 _player.getPlaylist()[0]['captions.file'] = _options.file; 171 } 172 if(_options.files) { 173 _player.getPlaylist()[0]['captions.files'] = _options.files; 174 } 175 if(_options.labels) { 176 _player.getPlaylist()[0]['captions.labels'] = _options.labels; 177 } 178 }; 179 180 181 /** Update the interface. **/ 182 function _redraw() { 183 if(!_tracks.length) { 184 _player.getPlugin("dock").setButton('captions',dockHandler,_icons[0]); 185 _renderer.hide(); 186 } else if (_options.state) { 187 _player.getPlugin("dock").setButton('captions',dockHandler,_icons[2]); 188 if(_state == 'playing') { 189 _renderer.show(); 190 } else { 191 _renderer.hide(); 192 } 193 } else { 194 _player.getPlugin("dock").setButton('captions',dockHandler,_icons[1]); 195 _renderer.hide(); 196 } 197 }; 198 199 /** Reposition elements upon a resize. **/ 200 this.resize = function(width,height) { 201 if(_player.getRenderingMode() == 'flash') { return; } 202 _renderer.resize(width,height); 203 _selector.resize(width,height); 204 }; 205 206 207 /** Set dock buttons when player is ready. **/ 208 function _setup() { 209 if(_player.getRenderingMode() == 'flash') { return; } 210 // Listen to player events 211 _player.onPlaylist(_playlistHandler); 212 _player.onPlaylistItem(_itemHandler); 213 _player.onIdle(_idleHandler); 214 _player.onPlay(_playHandler); 215 _player.onTime(_timeHandler); 216 // Grab cookies and config options 217 if(_cookie('state') !== null) { 218 if(_cookie('state') == 'true') { 219 _options.state = true; 220 } else { 221 _options.state = false; 222 } 223 } 224 if(_cookie('label') !== null) { 225 _options.label = _cookie('label'); 226 } 227 for (var option in options) { 228 _options[option] = options[option]; 229 } 230 // Place renderer and selector. 231 _renderer = new jwplayer.captions.renderer(_options,_div); 232 _selector = new jwplayer.captions.selector(_selectorHandler,_div); 233 _redraw(); 234 }; 235 _player.onReady(_setup); 236 237 238 /** Selection menu was closed. **/ 239 function _selectorHandler(index) { 240 // Show dock/display for 5.7+ 241 _selector.hide(); 242 try { 243 _player.getPlugin('display').show(); 244 _player.getPlugin('dock').show(); 245 } catch (error) {} 246 // Store new state and track 247 if(index > 0) { 248 _options.state = true; 249 _track = index - 1; 250 _options.label = _tracks[_track].label; 251 } else { 252 _config.state = false; 253 } 254 _cookie('label',_options.label); 255 _cookie('state',_options.state); 256 // Load new captions 257 if(_tracks[_track].data) { 258 _renderer.populate(_tracks[_track].data); 259 } else { 260 _load(_tracks[_track].file); 261 } 262 _redraw(); 263 }; 264 265 266 /** Listen to player time updates. **/ 267 function _timeHandler(event) { 268 _renderer.update(event.position); 269 }; 270 271 11 272 }; 12 _player.onReady(_setup); 13 14 15 /** Reposition elements upon a resize. **/ 16 this.resize = function(width,height) { 17 if(_player.getRenderingMode() == 'flash') { return; } 18 }; 19 20 21 /** Apply CSS styles to elements. **/ 22 function _style(element,styles) { 23 for(var property in styles) { 24 element.style[property] = styles[property]; 25 } 26 }; 27 28 29 }; 30 31 32 /** Register the plugin with JW Player. **/ 33 jwplayer().registerPlugin('captions', template,'./captions.swf'); 273 274 275 /** Claim the namespace and register the plugin. **/ 276 jwplayer.captions = {}; 277 jwplayer().registerPlugin('captions', template,'./captions.swf'); 34 278 35 279 -
plugins/captions/src/js/captions.renderer.js
r1941 r1973 1 (function(jwplayer) { 2 3 4 /** Component that renders the actual captions on screen. **/ 5 jwplayer.captions.renderer = function(_options,_div) { 6 7 8 /** Current list with captions. **/ 9 var _captions; 10 /** Container with captions data. **/ 11 var _container; 12 /** Current video position. **/ 13 var _position; 14 /** Current actie captions entry. **/ 15 var _current; 16 17 18 /** Hide the rendering component. **/ 19 this.hide = function() { 20 _style({display:'none'}); 21 }; 22 23 24 /** Assign list of captions to the renderer. **/ 25 this.populate = function(captions) { 26 _current = -1; 27 _captions = captions; 28 _select(); 29 }; 30 31 32 /** Render the active caption. **/ 33 function _render(html) { 34 _container.innerHTML = html; 35 }; 36 37 38 /** Resize the captions. **/ 39 this.resize = function(width,height) { 40 /** 41 if(_player.config.fullscreen) { 42 _renderer.x = width / 8; 43 _renderer.width = width * 3 / 4; 44 } else { 45 _renderer.x = width / 24; 46 _renderer.width = width * 11 / 12; 47 } 48 _renderer.scaleY = _renderer.scaleX; 49 // Position the captions, taking controls into account. 50 if (_player.config.fullscreen) { 51 _renderer.y = height - 70; 52 } else if (_player.config.controlbar == 'over') { 53 _renderer.y = height - 50; 54 } else { 55 _renderer.y = height - 20; 56 } 57 **/ 58 }; 59 60 61 /** Select a caption for rendering. **/ 62 function _select() { 63 var found = -1; 64 for (var i=0; i < _captions.length; i++) { 65 if (_captions[i]['begin'] <= _position && 66 (i == _captions.length-1 || _captions[i+1]['begin'] >= _position)) { 67 found = i; 68 break; 69 } 70 } 71 // If none, empty the text. If not current, re-render. 72 if(found == -1) { 73 _render(''); 74 } else if (found != _current) { 75 _current = found; 76 _render(_captions[i]['text']); 77 } 78 }; 79 80 81 /** Constructor for the renderer. **/ 82 function _setup() { 83 _container = document.createElement("p"); 84 _div.appendChild(_container); 85 _style({ 86 color: _options.color, 87 fontFamily: _options.fontFamily, 88 fontSize: _options.fontSize+'px', 89 fontStyle: _options.fontStyle, 90 fontWeight: _options.fontWeight, 91 lineHeight: Math.round(_options.fontSize * 1.4)+'px', 92 textAlign: 'center', 93 textDecoration: _options.textDecoration 94 }); 95 if(_options.back) { 96 _style({textShadow: '#000 1px 1px 0'}); 97 } else { 98 _style({background:'#000'}); 99 } 100 }; 101 _setup(); 102 103 104 /** Show the rendering component. **/ 105 this.show = function() { 106 _style({display:'block'}); 107 }; 108 109 110 /** Apply CSS styles to elements. **/ 111 function _style(styles) { 112 for(var property in styles) { 113 _container.style[property] = styles[property]; 114 } 115 }; 116 117 118 /** Update the video position. **/ 119 this.update = function(position) { 120 _position = position; 121 if(_captions) { 122 _select(); 123 } 124 }; 125 126 127 }; 128 129 130 })(jwplayer); -
plugins/captions/src/js/captions.selector.js
r1941 r1973 1 (function(jwplayer) { 2 3 4 /** Component that renders a selection menu. **/ 5 jwplayer.captions.selector = function(_callback,_div) { 6 7 8 /** Hide the language selector. **/ 9 this.hide = function() {}; 10 11 12 /** Polulate the selector with a list of options. **/ 13 this.populate = function(options, active) {}; 14 15 16 /** Resize the selector to fit the display. **/ 17 this.resize = function(width,height) {}; 18 19 20 /** Show the language selector. **/ 21 this.show = function() {}; 22 23 24 /** Apply CSS styles to elements. **/ 25 function _style(element,styles) { 26 for(var property in styles) { 27 element.style[property] = styles[property]; 28 } 29 }; 30 31 32 }; 33 34 35 })(jwplayer); -
plugins/captions/src/js/captions.srt.js
r1941 r1973 1 (function(jwplayer) { 2 3 4 /** Component that loads and parses an SRT file. **/ 5 jwplayer.captions.srt = function(_success, _failure) { 6 7 8 /** XMLHTTP Object. **/ 9 var _request; 10 /** URL of the SRT file. **/ 11 var _url; 12 13 14 /** Handle errors. **/ 15 function _error(status) { 16 if(status == 0) { 17 _failure("Crossdomain loading denied: "+_url); 18 } else if (status == 404) { 19 _failure("SRT File not found: "+_url); 20 } else { 21 _failure("Error "+status+" loading SRT file: "+_url); 22 } 23 }; 24 25 26 /** Load a new SRT file. **/ 27 this.load = function(url) { 28 _url = url; 29 try { 30 _request.open("GET", url, true); 31 _request.send(null); 32 } catch (error) { 33 _failure("Error loading SRT File: "+url); 34 } 35 }; 36 37 38 /** Proceed from loading to parsing. **/ 39 function _parse(data) { 40 _captions = [{begin:0,text:''}]; 41 // Trim whitespace and split the list by returns. 42 data = data.replace(/^\s+/, '').replace(/\s+$/, ''); 43 var list = data.split("\r\n\r\n"); 44 if(list.length == 1) { list = data.split("\n\n"); } 45 for(var i=0; i<list.length; i++) { 46 // Parse each entry 47 var entry = _entry(list[i]); 48 if(entry['begin'] && entry['text']) { 49 _captions.push(entry); 50 // Insert empty caption at the end. 51 if(entry['end']) { 52 _captions.push({begin:entry['end'],text:''}); 53 delete entry['end']; 54 } 55 } 56 } 57 if(_captions.length > 1) { 58 _success(_captions); 59 } else { 60 _failure("Invalid SRT file: "+_url); 61 } 62 }; 63 64 65 /** Parse a single captions entry. **/ 66 function _entry(data) { 67 var entry = {}; 68 var array = data.split("\r\n"); 69 if(array.length == 1) { array = data.split("\n"); } 70 try { 71 // Second line contains the start and end. 72 var index = array[1].indexOf(' --> '); 73 if(index > 0) { 74 entry['begin'] = _seconds(array[1].substr(0,index)); 75 entry['end'] = _seconds(array[1].substr(index+5)); 76 } 77 // Third line starts the text. 78 if(array[2]) { 79 entry['text'] = array[2]; 80 // Arbitrary number of additional lines. 81 for (var i=3; i<array.length; i++) { 82 entry['text'] += '<br/>' + array[i]; 83 } 84 } 85 } catch (error) {} 86 return entry; 87 }; 88 89 90 /** Convert timecode to seconds. **/ 91 function _seconds(string) { 92 string = string.replace(',', '.'); 93 var array = string.split(':'); 94 var number = 0; 95 if (string.substr(-1) == 's') { 96 number = Number(string.substr(0, string.length - 1)); 97 } else if (string.substr(-1) == 'm') { 98 number = Number(string.substr(0, string.length - 1)) * 60; 99 } else if (string.substr(-1) == 'h') { 100 number = Number(string.substr(0, string.length - 1)) * 3600; 101 } else if (array.length > 1) { 102 number = Number(array[array.length - 1]); 103 number += Number(array[array.length - 2]) * 60; 104 if (array.length == 3) { 105 number += Number(array[array.length - 3]) * 3600; 106 } 107 } else { 108 number = Number(string); 109 } 110 return number; 111 }; 112 113 114 /** Setup the SRT parser. **/ 115 function _setup() { 116 _request = new XMLHttpRequest(); 117 _request.onreadystatechange = function() { 118 if (_request.readyState === 4) { 119 if (_request.status === 200) { 120 _parse(_request.responseText); 121 } else { 122 _error(_request.status); 123 } 124 } 125 }; 126 }; 127 _setup(); 128 129 130 }; 131 132 133 })(jwplayer); -
plugins/captions/test/assets/bunny-ned.txt
r1964 r1973 9 9 3 10 10 00:00:11,000 --> 00:00:13,000 11 Drie kna agdieren11 Drie knagers 12 12 13 13 4 -
plugins/captions/test/assets/playlist.xml
r1769 r1973 6 6 <title>Coronation Street</title> 7 7 <description>Single, external XML captions.</description> 8 <jwplayer:file>http://content.bitsontherun.com/videos/7OCSON1y -393434.flv</jwplayer:file>8 <jwplayer:file>http://content.bitsontherun.com/videos/7OCSON1y.mp4</jwplayer:file> 9 9 <jwplayer:image>http://content.bitsontherun.com/thumbs/7OCSON1y-320.jpg</jwplayer:image> 10 10 <jwplayer:captions.file>assets/corrie.xml</jwplayer:captions.file> -
plugins/captions/test/basic.html
r1964 r1973 5 5 <meta charset="UTF-8"> 6 6 <script type="text/javascript" src="assets/jwplayer.min.js"></script> 7 <title> Single Track</title>7 <title>Basic Setup</title> 8 8 <style> 9 9 body { padding: 50px; font: 13px/20px Arial; background: #EEE; } 10 10 form,p, ul { margin-top: 20px; } 11 #player { -webkit-box-shadow: 0 0 5px #999; background: #000; color:#FFF; line-height:270px; text-align: center;}11 #player { -webkit-box-shadow: 0 0 5px #999; } 12 12 </style> 13 13 … … 15 15 <body> 16 16 17 <h2> Single Track</h2>17 <h2>Basic Setup</h2> 18 18 19 19 <div id="player"></div> … … 21 21 function loadPlayer(key,captions) { 22 22 var options = { 23 file: 'http://content.bitsontherun.com/videos/'+key+' -393434.flv',23 file: 'http://content.bitsontherun.com/videos/'+key+'.mp4', 24 24 height: 270, 25 image: 'http://content.bitsontherun.com/thumbs/'+key +'-480.jpg',25 image: 'http://content.bitsontherun.com/thumbs/'+key.substr(0,8)+'-480.jpg', 26 26 plugins: { 27 27 '../captions.js': {} … … 42 42 <li><a href="javascript:loadPlayer('7OCSON1y','assets/corrie.srt')">srt captions</a></li> 43 43 <li><a href="javascript:loadPlayer('7OCSON1y','assets/corrie.xml')">dfxp captions</a></li> 44 <li><a href="javascript:loadPlayer('aytCR4cx')">mp4 captions</a></li> 45 <li><a href="javascript:loadPlayer('7OCSON1y','assets/corri.xml')">nonexisting file</a></li> 44 <li><a href="javascript:loadPlayer('aytCR4cx-393434')">mp4 captions</a></li> 46 45 </ul> 47 46 -
plugins/captions/test/compatibility.html
r1964 r1973 9 9 body { padding: 50px; font: 13px/20px Arial; background: #EEE; } 10 10 #player, p, ul { margin-top: 20px; display: block; } 11 #player { -webkit-box-shadow: 0 0 5px #999; background: #000; color:#FFF; line-height:270px; text-align: center;}11 #player { -webkit-box-shadow: 0 0 5px #999; } 12 12 </style> 13 13 -
plugins/captions/test/index.html
r1964 r1973 27 27 <ul> 28 28 <li><a href="compatibility.html">Backward Compatibility</a></li> 29 <li><a href="errors.html">Error Handling</a></li> 29 30 <li><a href="ova.html">OVA Support</a></li> 30 31 </ul> -
plugins/captions/test/modes.html
r1964 r1973 9 9 body { padding: 50px; font: 13px/20px Arial; background: #EEE; } 10 10 form,p, ul { margin-top: 20px; } 11 #player { -webkit-box-shadow: 0 0 5px #999; background: #000; color:#FFF;}11 #player { -webkit-box-shadow: 0 0 5px #999;} 12 12 </style> 13 13 -
plugins/captions/test/multiple.html
r1964 r1973 44 44 45 45 <ul> 46 <li><a href="javascript:loadPlayer({file:'http://content.bitsontherun.com/ jwp/aytCR4cx.xml'},{files:'assets/bunny-eng.txt,assets/bunny-ned.txt',labels:'English,Nederlands'})">2 external srt tracks</a></li>46 <li><a href="javascript:loadPlayer({file:'http://content.bitsontherun.com/videos/aytCR4cx.mp4'},{files:'assets/bunny-eng.txt,assets/bunny-ned.txt',labels:'English,Nederlands'})">2 external srt tracks</a></li> 47 47 48 48 <li><a href="javascript:loadPlayer({file:'http://content.bitsontherun.com/videos/w5VkaqJ1-393434.mp4',image:'http://content.bitsontherun.com/thumbs/w5VkaqJ1-480.jpg'},{})">6 embedded mp4 tracks</a></li> 49 49 50 <li><a href="javascript:loadPlayer({file:'http://content.bitsontherun.com/jwp/a95zAVN1.xml'},{files:'assets/sintel-chi.txt,assets/sintel-deu.txt,assets/sintel-dut.txt,assets/sintel-eng.txt,assets/sintel-far.txt,assets/sintel-fra.txt,assets/sintel-gre.txt,assets/sintel-ita.txt,assets/sintel-jpn.txt,assets/sintel-kor.txt,assets/sintel-pol.txt,assets/sintel-por.txt,assets/sintel-rus.txt,assets/sintel-spa.txt,assets/sintel-srp.txt,assets/sintel-tur.txt',labels:'Chinese,German,Dutch,English,Farsi,French,Greek,Italian,Japanese,Korean,Polish,Portuguese,Russian,Spanish,Serbian,Turkish'})">16 external srt tracks</a></li> 50 <li><a href="javascript:loadPlayer({file:'http://content.bitsontherun.com/videos/a95zAVN1.mp4'},{files:'assets/sintel-chi.txt,assets/sintel-far.txt,assets/sintel-gre.txt,assets/sintel-jpn.txt,assets/sintel-kor.txt,assets/sintel-pol.txt,assets/sintel-rus.txt,assets/sintel-srp.txt,assets/sintel-tur.txt',labels:'Chinese,Farsi,Greek,Japanese,Korean,Polish,Russian,Serbian,Turkish'})">9 external srt tracks</a></li> 51 <li><a href="javascript:loadPlayer({file:'http://content.bitsontherun.com/videos/aytCR4cx.mp4'},{files:'assets/bunny-eng.txt,assets/bunny-ned.txt'})">2 srt tracks, no labels</a></li> 52 51 53 52 54 </ul> -
plugins/captions/test/options.html
r1964 r1973 19 19 <div id="player"></div> 20 20 <script type="text/javascript"> 21 function loadPlayer( dock,back,state) {21 function loadPlayer(back,state) { 22 22 var options = { 23 23 controlbar: 'bottom', 24 file: 'http://content.bitsontherun.com/videos/ aytCR4cx-393434.mp4',24 file: 'http://content.bitsontherun.com/videos/7OCSON1y.mp4', 25 25 height: 296, 26 image: 'http://content.bitsontherun.com/thumbs/ aytCR4cx-480.jpg',26 image: 'http://content.bitsontherun.com/thumbs/7OCSON1y-480.jpg', 27 27 plugins: { 28 '../captions.js': {} 28 '../captions.js': { 29 file: 'assets/corrie.srt' 30 } 29 31 }, 30 32 flashplayer: 'assets/player.swf', 31 33 width: 480 32 34 }; 33 if(dock !== undefined) { 34 options.dock = dock; 35 options.plugins['../captions.swf'].back = back; 36 options.plugins['../captions.swf'].state = state; 35 if(back !== undefined) { 36 options.plugins['../captions.js'].back = back; 37 options.plugins['../captions.js'].state = state; 37 38 } 38 39 jwplayer("player").setup(options); … … 43 44 <ul> 44 45 <li><a href="javascript:loadPlayer()">Default options</a></li> 45 <li><a href="javascript:loadPlayer(true,true ,true)">Dock true, back true, state true</a></li>46 <li><a href="javascript:loadPlayer(false,false ,false)">Dock false, back false, state false</a></li>46 <li><a href="javascript:loadPlayer(true,true)">Back true, state true</a></li> 47 <li><a href="javascript:loadPlayer(false,false)">Back false, state false</a></li> 47 48 </ul> 48 49 -
plugins/captions/test/playlist.html
r1964 r1973 9 9 body { padding: 50px; font: 13px/20px Arial; background: #EEE; } 10 10 form,p, ul { margin-top: 20px; } 11 #player { -webkit-box-shadow: 0 0 5px #999; background: #000; color:#FFF; line-height:270px; text-align: center;}11 #player { -webkit-box-shadow: 0 0 5px #999; } 12 12 </style> 13 13 … … 32 32 width: 800 33 33 } 34 if(typeof(list) == 'string') { 34 if(typeof(list) == 'string') { 35 35 options.file = list; 36 36 } else { … … 43 43 title: 'Coronation Street', 44 44 description: 'Single, external XML captions.', 45 file: 'http://content.bitsontherun.com/videos/7OCSON1y -393434.flv',45 file: 'http://content.bitsontherun.com/videos/7OCSON1y.mp4', 46 46 image: 'http://content.bitsontherun.com/thumbs/7OCSON1y-320.jpg', 47 47 'captions.file': 'assets/corrie.xml' … … 49 49 title:'Big Buck Bunny', 50 50 description: 'Single, embedded MP4 captions.', 51 file: 'http://content.bitsontherun.com/videos/aytCR4cx -393434.mp4',51 file: 'http://content.bitsontherun.com/videos/aytCR4cx.mp4', 52 52 image: 'http://content.bitsontherun.com/thumbs/aytCR4cx-320.jpg' 53 53 },{ 54 54 title: 'Men With Talent', 55 55 description: 'No captions at all.', 56 file: 'http://content.bitsontherun.com/videos/SAs4hE5G -364766.mp4',56 file: 'http://content.bitsontherun.com/videos/SAs4hE5G.mp4', 57 57 image: 'http://content.bitsontherun.com/thumbs/SAs4hE5G-320.jpg' 58 58 },{ 59 59 title: 'Global Timoto', 60 60 description: 'Multiple, embedded MP4 captions.', 61 file: 'http://content.bitsontherun.com/videos/w5VkaqJ1 -393434.mp4',61 file: 'http://content.bitsontherun.com/videos/w5VkaqJ1.mp4', 62 62 image: 'http://content.bitsontherun.com/thumbs/w5VkaqJ1-320.jpg' 63 63 },{ 64 64 title: 'Sintel', 65 65 description: 'Multiple, external SRT captions.', 66 file: 'http://content.bitsontherun.com/videos/q1fx20VZ -364765.mp4',66 file: 'http://content.bitsontherun.com/videos/q1fx20VZ.mp4', 67 67 image: 'http://content.bitsontherun.com/thumbs/q1fx20VZ-320.jpg', 68 68 'captions.files': 'assets/sintel-dut.txt,assets/sintel-eng.txt,assets/sintel-fra.txt,assets/sintel-deu.txt,assets/sintel-ita.txt,assets/sintel-pol.txt,assets/sintel-por.txt,assets/sintel-rus.txt,assets/sintel-spa.txt' … … 75 75 </ul> 76 76 <ul> 77 <li><a href="javascript:jwplayer().load({file:'http://content.bitsontherun.com/videos/7OCSON1y -393434.flv','captions.file':'assets/corrie.xml',title: 'Coronation Street'})">load() one video</a>77 <li><a href="javascript:jwplayer().load({file:'http://content.bitsontherun.com/videos/7OCSON1y.mp4','captions.file':'assets/corrie.xml',title: 'Coronation Street'})">load() one video</a> 78 78 <li><a href="javascript:jwplayer().load('assets/playlist.xml')">load() RSS feed</a> 79 79 </ul>
Note: See TracChangeset
for help on using the changeset viewer.
