webshims-rails 0.4.2 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. data/lib/webshims-rails/version.rb +2 -2
  2. data/vendor/assets/javascripts/webshims/minified/polyfiller.js +30 -29
  3. data/vendor/assets/javascripts/webshims/minified/shims/combos/1.js +12 -12
  4. data/vendor/assets/javascripts/webshims/minified/shims/combos/10.js +76 -76
  5. data/vendor/assets/javascripts/webshims/minified/shims/combos/11.js +12 -12
  6. data/vendor/assets/javascripts/webshims/minified/shims/combos/12.js +12 -12
  7. data/vendor/assets/javascripts/webshims/minified/shims/combos/13.js +27 -27
  8. data/vendor/assets/javascripts/webshims/minified/shims/combos/16.js +12 -12
  9. data/vendor/assets/javascripts/webshims/minified/shims/combos/17.js +14 -14
  10. data/vendor/assets/javascripts/webshims/minified/shims/combos/18.js +63 -60
  11. data/vendor/assets/javascripts/webshims/minified/shims/combos/19.js +59 -59
  12. data/vendor/assets/javascripts/webshims/minified/shims/combos/20.js +1 -1
  13. data/vendor/assets/javascripts/webshims/minified/shims/combos/22.js +1 -1
  14. data/vendor/assets/javascripts/webshims/minified/shims/combos/24.js +67 -67
  15. data/vendor/assets/javascripts/webshims/minified/shims/combos/25.js +59 -58
  16. data/vendor/assets/javascripts/webshims/minified/shims/combos/26.js +81 -80
  17. data/vendor/assets/javascripts/webshims/minified/shims/combos/27.js +103 -102
  18. data/vendor/assets/javascripts/webshims/minified/shims/combos/6.js +34 -31
  19. data/vendor/assets/javascripts/webshims/minified/shims/combos/7.js +41 -38
  20. data/vendor/assets/javascripts/webshims/minified/shims/combos/8.js +35 -35
  21. data/vendor/assets/javascripts/webshims/minified/shims/combos/9.js +67 -67
  22. data/vendor/assets/javascripts/webshims/minified/shims/dom-extend.js +17 -17
  23. data/vendor/assets/javascripts/webshims/minified/shims/form-number-date-api.js +10 -8
  24. data/vendor/assets/javascripts/webshims/minified/shims/form-number-date-ui.js +24 -23
  25. data/vendor/assets/javascripts/webshims/minified/shims/mediaelement-swf.js +1 -1
  26. data/vendor/assets/javascripts/webshims/minified/shims/styles/shim.css +9 -0
  27. data/vendor/assets/javascripts/webshims/minified/shims/track-ui.js +9 -9
  28. data/vendor/assets/javascripts/webshims/minified/shims/track.js +21 -20
  29. data/vendor/assets/javascripts/webshims/polyfiller.js +144 -140
  30. data/vendor/assets/javascripts/webshims/shims/combos/1.js +10 -6
  31. data/vendor/assets/javascripts/webshims/shims/combos/10.js +11 -7
  32. data/vendor/assets/javascripts/webshims/shims/combos/11.js +10 -6
  33. data/vendor/assets/javascripts/webshims/shims/combos/12.js +10 -6
  34. data/vendor/assets/javascripts/webshims/shims/combos/13.js +10 -6
  35. data/vendor/assets/javascripts/webshims/shims/combos/16.js +10 -6
  36. data/vendor/assets/javascripts/webshims/shims/combos/17.js +10 -6
  37. data/vendor/assets/javascripts/webshims/shims/combos/18.js +986 -924
  38. data/vendor/assets/javascripts/webshims/shims/combos/19.js +10 -6
  39. data/vendor/assets/javascripts/webshims/shims/combos/20.js +1 -1
  40. data/vendor/assets/javascripts/webshims/shims/combos/22.js +1 -1
  41. data/vendor/assets/javascripts/webshims/shims/combos/24.js +10 -6
  42. data/vendor/assets/javascripts/webshims/shims/combos/25.js +820 -768
  43. data/vendor/assets/javascripts/webshims/shims/combos/26.js +820 -768
  44. data/vendor/assets/javascripts/webshims/shims/combos/27.js +821 -769
  45. data/vendor/assets/javascripts/webshims/shims/combos/6.js +986 -924
  46. data/vendor/assets/javascripts/webshims/shims/combos/7.js +986 -924
  47. data/vendor/assets/javascripts/webshims/shims/combos/8.js +10 -6
  48. data/vendor/assets/javascripts/webshims/shims/combos/9.js +11 -7
  49. data/vendor/assets/javascripts/webshims/shims/dom-extend.js +10 -6
  50. data/vendor/assets/javascripts/webshims/shims/form-number-date-api.js +77 -77
  51. data/vendor/assets/javascripts/webshims/shims/form-number-date-ui.js +909 -847
  52. data/vendor/assets/javascripts/webshims/shims/mediaelement-swf.js +1 -1
  53. data/vendor/assets/javascripts/webshims/shims/styles/shim.css +9 -0
  54. data/vendor/assets/javascripts/webshims/shims/track-ui.js +300 -291
  55. data/vendor/assets/javascripts/webshims/shims/track.js +810 -762
  56. metadata +10 -5
@@ -1190,7 +1190,7 @@ jQuery.webshims.register('dom-extend', function($, webshims, window, document, u
1190
1190
  var docObserve = {
1191
1191
  init: false,
1192
1192
  start: function(){
1193
- if(!this.init){
1193
+ if(!this.init && document.body){
1194
1194
  this.init = true;
1195
1195
  this.height = $(document).height();
1196
1196
  this.width = $(document).width();
@@ -1202,7 +1202,7 @@ jQuery.webshims.register('dom-extend', function($, webshims, window, document, u
1202
1202
  docObserve.width = width;
1203
1203
  handler({type: 'docresize'});
1204
1204
  }
1205
- }, 400);
1205
+ }, 600);
1206
1206
  }
1207
1207
  }
1208
1208
  };
@@ -1218,8 +1218,10 @@ jQuery.webshims.register('dom-extend', function($, webshims, window, document, u
1218
1218
  }
1219
1219
  lastHeight = height;
1220
1220
  lastWidth = width;
1221
- docObserve.height = $(document).height();
1222
- docObserve.width = $(document).width();
1221
+ if(document.body){
1222
+ docObserve.height = $(document).height();
1223
+ docObserve.width = $(document).width();
1224
+ }
1223
1225
  }
1224
1226
  $.event.trigger('updateshadowdom');
1225
1227
  }, 40);
@@ -1265,7 +1267,9 @@ jQuery.webshims.register('dom-extend', function($, webshims, window, document, u
1265
1267
  shadowFocusElementData.shadowData.data = shadowData.shadowData.data = nativeData.shadowData.data = opts.data;
1266
1268
  }
1267
1269
  opts = null;
1268
- docObserve.start();
1270
+ webshims.ready('DOM', function(){
1271
+ docObserve.start();
1272
+ });
1269
1273
  }
1270
1274
  })(),
1271
1275
  propTypes: {
@@ -1409,7 +1413,7 @@ jQuery.webshims.register('dom-extend', function($, webshims, window, document, u
1409
1413
  }
1410
1414
  if(propType){
1411
1415
  if(descs[prop][propType]){
1412
- webshims.log('override: '+ name +'['+prop +'] for '+ propType);
1416
+ //webshims.log('override: '+ name +'['+prop +'] for '+ propType);
1413
1417
  } else {
1414
1418
  descs[prop][propType] = {};
1415
1419
  ['value', 'set', 'get'].forEach(function(copyProp){
@@ -3054,7 +3058,7 @@ jQuery.webshims.register('mediaelement-swf', function($, webshims, window, docum
3054
3058
  if(flash[0].offsetWidth > 1 && flash[0].offsetHeight > 1 && location.protocol.indexOf('file:') === 0){
3055
3059
  webshims.error("Add your local development-directory to the local-trusted security sandbox: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html");
3056
3060
  } else if(flash[0].offsetWidth < 2 || flash[0].offsetHeight < 2) {
3057
- webshims.info("JS-SWF connection can't be established on hidden or unconnected flash objects");
3061
+ webshims.warn("JS-SWF connection can't be established on hidden or unconnected flash objects");
3058
3062
  }
3059
3063
  flash = null;
3060
3064
  }, 8000);
@@ -3314,766 +3318,814 @@ jQuery.webshims.register('mediaelement-swf', function($, webshims, window, docum
3314
3318
  }, 'prop');
3315
3319
  }
3316
3320
 
3317
- });jQuery.webshims.register('track', function($, webshims, window, document, undefined){
3318
- var mediaelement = webshims.mediaelement;
3319
- var id = new Date().getTime();
3320
- var showTracks = {subtitles: 1, captions: 1};
3321
- var notImplemented = function(){
3322
- webshims.error('not implemented yet');
3323
- };
3324
-
3325
- var createEventTarget = function(obj){
3326
- var eventList = {};
3327
- obj.addEventListener = function(name, fn){
3328
- if(eventList[name]){
3329
- webshims.error('always use $.bind to the shimed event: '+ name +' already bound fn was: '+ eventList[name] +' your fn was: '+ fn);
3330
- }
3331
- eventList[name] = fn;
3332
-
3333
- };
3334
- obj.removeEventListener = function(name, fn){
3335
- if(eventList[name] && eventList[name] != fn){
3336
- webshims.error('always use $.bind/$.unbind to the shimed event: '+ name +' already bound fn was: '+ eventList[name] +' your fn was: '+ fn);
3337
- }
3338
- if(eventList[name]){
3339
- delete eventList[name];
3340
- }
3341
- };
3342
- return obj;
3343
- };
3344
-
3345
-
3346
- var cueListProto = {
3347
- getCueById: function(id){
3348
- var cue = null;
3349
- for(var i = 0, len = this.length; i < len; i++){
3350
- if(this[i].id === id){
3351
- cue = this[i];
3352
- break;
3353
- }
3354
- }
3355
- return cue;
3356
- }
3357
- };
3358
- var textTrackProto = {
3359
- shimActiveCues: null,
3360
- _shimActiveCues: null,
3361
- activeCues: null,
3362
- cues: null,
3363
- kind: 'subtitles',
3364
- label: '',
3365
- language: '',
3366
- mode: 'disabled',
3367
- readyState: 0,
3368
- oncuechange: null,
3369
- toString: function() {
3370
- return "[object TextTrack]";
3371
- },
3372
- addCue: function(cue){
3373
- if(!this.cues){
3374
- this.cues = mediaelement.createCueList();
3375
- } else {
3376
- var lastCue = this.cues[this.cues.length-1];
3377
- if(lastCue && lastCue.startTime > cue.startTime){
3378
- webshims.error("cue startTime higher than previous cue's startTime");
3379
- }
3380
- }
3381
- if(cue.track){
3382
- webshims.error("cue already part of a track element");
3383
- }
3384
- cue.track = this;
3385
- this.cues.push(cue);
3386
- },
3387
- removeCue: notImplemented,
3388
- DISABLED: 'disabled',
3389
- OFF: 'disabled',
3390
- HIDDEN: 'hidden',
3391
- SHOWING: 'showing',
3392
- ERROR: 3,
3393
- LOADED: 2,
3394
- LOADING: 1,
3395
- NONE: 0
3396
- };
3397
- var copyProps = ['kind', 'label', 'srclang'];
3398
-
3399
- var owns = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
3400
-
3401
- //ToDo: add/remove event
3402
- var updateMediaTrackList = function(baseData, trackList){
3403
- var removed = [];
3404
- var added = [];
3405
- var newTracks = [];
3406
- var i, len;
3407
- if(!baseData){
3408
- baseData = webshims.data(this, 'mediaelementBase') || webshims.data(this, 'mediaelementBase', {});
3409
- }
3410
-
3411
- if(!trackList){
3412
- baseData.blockTrackListUpdate = true;
3413
- trackList = $.prop(this, 'textTracks');
3414
- baseData.blockTrackListUpdate = false;
3415
- }
3416
-
3417
- clearTimeout(baseData.updateTrackListTimer);
3418
-
3419
- $('track', this).each(function(){
3420
- var track = $.prop(this, 'track');
3421
- newTracks.push(track);
3422
- if(trackList.indexOf(track) == -1){
3423
- added.push(track);
3424
- }
3425
- });
3426
-
3427
- if(baseData.scriptedTextTracks){
3428
- for(i = 0, len = baseData.scriptedTextTracks.length; i < len; i++){
3429
- newTracks.push(baseData.scriptedTextTracks[i]);
3430
- if(trackList.indexOf(baseData.scriptedTextTracks[i]) == -1){
3431
- added.push(baseData.scriptedTextTracks[i]);
3432
- }
3433
- }
3434
- }
3435
-
3436
- for(i = 0, len = trackList.length; i < len; i++){
3437
- if(newTracks.indexOf(trackList[i]) == -1){
3438
- removed.push(trackList[i]);
3439
- }
3440
- }
3441
-
3442
- if(removed.length || added.length){
3443
- trackList.splice(0);
3444
-
3445
- for(i = 0, len = newTracks.length; i < len; i++){
3446
- trackList.push(newTracks[i]);
3447
- }
3448
- for(i = 0, len = removed.length; i < len; i++){
3449
- $([trackList]).triggerHandler($.Event({type: 'removetrack', track: trackList, track: removed[i]}));
3450
- }
3451
- for(i = 0, len = added.length; i < len; i++){
3452
- $([trackList]).triggerHandler($.Event({type: 'addtrack', track: trackList, track: added[i]}));
3453
- }
3454
- if(baseData.scriptedTextTracks || removed.length){
3455
- $(this).triggerHandler('updatetrackdisplay');
3456
- }
3457
- }
3458
- };
3459
-
3460
- var refreshTrack = function(track, trackData){
3461
- var mode, kind;
3462
- if(!trackData){
3463
- trackData = webshims.data(track, 'trackData');
3464
- }
3465
- if(trackData && !trackData.isTriggering){
3466
- trackData.isTriggering = true;
3467
- mode = (trackData.track || {}).mode;
3468
- kind = (trackData.track || {}).kind;
3469
- setTimeout(function(){
3470
- if(mode !== (trackData.track || {}).mode || kind != (trackData.track || {}).kind){
3471
- if(!(trackData.track || {}).readyState){
3472
- $(track).triggerHandler('checktrackmode');
3473
- } else {
3474
- $(track).parent().triggerHandler('updatetrackdisplay');
3475
- }
3476
- }
3477
- trackData.isTriggering = false;
3478
-
3479
- }, 9);
3480
- }
3481
- };
3482
-
3483
- var emptyDiv = $('<div />')[0];
3484
- window.TextTrackCue = function(startTime, endTime, text){
3485
- if(arguments.length != 3){
3486
- webshims.error("wrong arguments.length for TextTrackCue.constructor");
3487
- }
3488
-
3489
- this.startTime = startTime;
3490
- this.endTime = endTime;
3491
- this.text = text;
3492
-
3493
- this.id = "";
3494
- this.pauseOnExit = false;
3495
-
3496
- createEventTarget(this);
3497
- };
3498
-
3499
- window.TextTrackCue.prototype = {
3500
-
3501
- onenter: null,
3502
- onexit: null,
3503
- pauseOnExit: false,
3504
- getCueAsHTML: function(){
3505
- var lastText = "";
3506
- var parsedText = "";
3507
- var fragment = document.createDocumentFragment();
3508
- var fn;
3509
- if(!owns(this, 'getCueAsHTML')){
3510
- fn = this.getCueAsHTML = function(){
3511
- var i, len;
3512
- if(lastText != this.text){
3513
- lastText = this.text;
3514
- parsedText = mediaelement.parseCueTextToHTML(lastText);
3515
- emptyDiv.innerHTML = parsedText;
3516
-
3517
- for(i = 0, len = emptyDiv.childNodes.length; i < len; i++){
3518
- fragment.appendChild(emptyDiv.childNodes[i].cloneNode(true));
3519
- }
3520
- }
3521
- return fragment.cloneNode(true);
3522
- };
3523
-
3524
- }
3525
- return fn ? fn.apply(this, arguments) : fragment.cloneNode(true);
3526
- },
3527
- track: null,
3528
-
3529
-
3530
- id: ''
3531
- //todo-->
3532
- // ,
3533
- // snapToLines: true,
3534
- // line: 'auto',
3535
- // size: 100,
3536
- // position: 50,
3537
- // vertical: '',
3538
- // align: 'middle'
3539
- };
3540
-
3541
-
3542
-
3543
-
3544
-
3545
- mediaelement.createCueList = function(){
3546
- return $.extend([], cueListProto);
3547
- };
3548
-
3549
- mediaelement.parseCueTextToHTML = (function(){
3550
- var tagSplits = /(<\/?[^>]+>)/ig;
3551
- var allowedTags = /^(?:c|v|ruby|rt|b|i|u)/;
3552
- var regEnd = /\<\s*\//;
3553
- var addToTemplate = function(localName, attribute, tag, html){
3554
- var ret;
3555
- if(regEnd.test(html)){
3556
- ret = '</'+ localName +'>';
3557
- } else {
3558
- tag.splice(0, 1);
3559
- ret = '<'+ localName +' '+ attribute +'="'+ (tag.join(' ').replace(/\"/g, '&#34;')) +'">';
3560
- }
3561
- return ret;
3562
- };
3563
- var replacer = function(html){
3564
- var tag = html.replace(/[<\/>]+/ig,"").split(/[\s\.]+/);
3565
- if(tag[0]){
3566
- tag[0] = tag[0].toLowerCase();
3567
- if(allowedTags.test(tag[0])){
3568
- if(tag[0] == 'c'){
3569
- html = addToTemplate('span', 'class', tag, html);
3570
- } else if(tag[0] == 'v'){
3571
- html = addToTemplate('q', 'title', tag, html);
3572
- }
3573
- } else {
3574
- html = "";
3575
- }
3576
- }
3577
- return html;
3578
- };
3579
-
3580
- return function(cueText){
3581
- return cueText.replace(tagSplits, replacer);
3582
- };
3583
- })();
3584
-
3585
- mediaelement.loadTextTrack = function(mediaelem, track, trackData, _default){
3586
- var loadEvents = 'play playing timeupdate updatetrackdisplay';
3587
- var obj = trackData.track;
3588
- var load = function(){
3589
- var src = $.prop(track, 'src');
3590
- var error;
3591
- var ajax;
3592
- if(obj.mode != 'disabled' && src && $.attr(track, 'src')){
3593
- $(mediaelem).unbind(loadEvents, load);
3594
- $(track).unbind('checktrackmode', load);
3595
- if(!obj.readyState){
3596
- error = function(){
3597
- obj.readyState = 3;
3598
- obj.cues = null;
3599
- obj.activeCues = obj.shimActiveCues = obj._shimActiveCues = null;
3600
- $(track).triggerHandler('error');
3601
- };
3602
- obj.readyState = 1;
3603
- try {
3604
- obj.cues = mediaelement.createCueList();
3605
- obj.activeCues = obj.shimActiveCues = obj._shimActiveCues = mediaelement.createCueList();
3606
- ajax = $.ajax({
3607
- dataType: 'text',
3608
- url: src,
3609
- success: function(text){
3610
- if(ajax.getResponseHeader('content-type') != 'text/vtt'){
3611
- webshims.error('set the mime-type of your WebVTT files to text/vtt. see: http://dev.w3.org/html5/webvtt/#text/vtt');
3612
- }
3613
- mediaelement.parseCaptions(text, obj, function(cues){
3614
- if(cues && 'length' in cues){
3615
- obj.readyState = 2;
3616
- $(track).triggerHandler('load');
3617
- $(mediaelem).triggerHandler('updatetrackdisplay');
3618
- } else {
3619
- error();
3620
- }
3621
- });
3622
-
3623
- },
3624
- error: error
3625
- });
3626
- } catch(er){
3627
- error();
3628
- webshims.warn(er);
3629
- }
3630
- }
3631
- }
3632
- };
3633
- obj.readyState = 0;
3634
- obj.shimActiveCues = null;
3635
- obj._shimActiveCues = null;
3636
- obj.activeCues = null;
3637
- obj.cues = null;
3638
- $(mediaelem).unbind(loadEvents, load);
3639
- $(track).unbind('checktrackmode', load);
3640
- $(mediaelem).bind(loadEvents, load);
3641
- $(track).bind('checktrackmode', load);
3642
- if(_default){
3643
- obj.mode = showTracks[obj.kind] ? 'showing' : 'hidden';
3644
- load();
3645
- }
3646
- };
3647
-
3648
- mediaelement.createTextTrack = function(mediaelem, track){
3649
- var obj, trackData;
3650
- if(track.nodeName){
3651
- trackData = webshims.data(track, 'trackData');
3652
-
3653
- if(trackData){
3654
- refreshTrack(track, trackData);
3655
- obj = trackData.track;
3656
- }
3657
- }
3658
-
3659
- if(!obj){
3660
- obj = createEventTarget(webshims.objectCreate(textTrackProto));
3661
- copyProps.forEach(function(copyProp){
3662
- var prop = $.prop(track, copyProp);
3663
- if(prop){
3664
- if(copyProp == 'srclang'){
3665
- copyProp = 'language';
3666
- }
3667
- obj[copyProp] = prop;
3668
- }
3669
- });
3670
-
3671
-
3672
- if(track.nodeName){
3673
- trackData = webshims.data(track, 'trackData', {track: obj});
3674
- mediaelement.loadTextTrack(mediaelem, track, trackData, $.prop(track, 'default'));
3675
- } else {
3676
- obj.cues = mediaelement.createCueList();
3677
- obj.activeCues = obj._shimActiveCues = obj.shimActiveCues = mediaelement.createCueList();
3678
- obj.mode = 'hidden';
3679
- obj.readyState = 2;
3680
- }
3681
- }
3682
- return obj;
3683
- };
3684
-
3685
-
3686
- /*
3687
- taken from:
3688
- Captionator 0.5.1 [CaptionCrunch]
3689
- Christopher Giffard, 2011
3690
- Share and enjoy
3691
-
3692
- https://github.com/cgiffard/Captionator
3693
-
3694
- modified for webshims
3695
- */
3696
- mediaelement.parseCaptionChunk = (function(){
3697
- // Set up timestamp parsers
3698
- var WebVTTTimestampParser = /^(\d{2})?:?(\d{2}):(\d{2})\.(\d+)\s+\-\-\>\s+(\d{2})?:?(\d{2}):(\d{2})\.(\d+)\s*(.*)/;
3699
- var GoogleTimestampParser = /^([\d\.]+)\s+\+([\d\.]+)\s*(.*)/;
3700
- var WebVTTDEFAULTSCueParser = /^(DEFAULTS|DEFAULT)\s+\-\-\>\s+(.*)/g;
3701
- var WebVTTSTYLECueParser = /^(STYLE|STYLES)\s+\-\-\>\s*\n([\s\S]*)/g;
3702
- var WebVTTCOMMENTCueParser = /^(COMMENT|COMMENTS)\s+\-\-\>\s+(.*)/g;
3703
-
3704
- return function(subtitleElement,objectCount){
3705
- var cueDefaults = [];
3706
-
3707
- var subtitleParts, timeIn, timeOut, html, timeData, subtitlePartIndex, cueSettings = "", id, specialCueData;
3708
- var timestampMatch, tmpCue;
3709
-
3710
- // WebVTT Special Cue Logic
3711
- if ((specialCueData = WebVTTDEFAULTSCueParser.exec(subtitleElement))) {
3712
- // cueDefaults = specialCueData.slice(2).join("");
3713
- // cueDefaults = cueDefaults.split(/\s+/g).filter(function(def) { return def && !!def.length; });
3714
- return null;
3715
- } else if ((specialCueData = WebVTTSTYLECueParser.exec(subtitleElement))) {
3716
- return null;
3717
- } else if ((specialCueData = WebVTTCOMMENTCueParser.exec(subtitleElement))) {
3718
- return null; // At this stage, we don't want to do anything with these.
3719
- }
3720
-
3721
- subtitleParts = subtitleElement.split(/\n/g);
3722
-
3723
- // Trim off any blank lines (logically, should only be max. one, but loop to be sure)
3724
- while (!subtitleParts[0].replace(/\s+/ig,"").length && subtitleParts.length > 0) {
3725
- subtitleParts.shift();
3726
- }
3727
-
3728
- if (subtitleParts[0].match(/^\s*[a-z0-9]+\s*$/ig)) {
3729
- // The identifier becomes the cue ID (when *we* load the cues from file. Programatically created cues can have an ID of whatever.)
3730
- id = String(subtitleParts.shift().replace(/\s*/ig,""));
3731
- }
3732
-
3733
- for (subtitlePartIndex = 0; subtitlePartIndex < subtitleParts.length; subtitlePartIndex ++) {
3734
- var timestamp = subtitleParts[subtitlePartIndex];
3735
-
3736
- if ((timestampMatch = WebVTTTimestampParser.exec(timestamp))) {
3737
-
3738
- // WebVTT
3739
-
3740
- timeData = timestampMatch.slice(1);
3741
-
3742
- timeIn = parseInt((timeData[0]||0) * 60 * 60,10) + // Hours
3743
- parseInt((timeData[1]||0) * 60,10) + // Minutes
3744
- parseInt((timeData[2]||0),10) + // Seconds
3745
- parseFloat("0." + (timeData[3]||0)); // MS
3746
-
3747
- timeOut = parseInt((timeData[4]||0) * 60 * 60,10) + // Hours
3748
- parseInt((timeData[5]||0) * 60,10) + // Minutes
3749
- parseInt((timeData[6]||0),10) + // Seconds
3750
- parseFloat("0." + (timeData[7]||0)); // MS
3751
- /*
3752
- if (timeData[8]) {
3753
- cueSettings = timeData[8];
3754
- }
3755
- */
3756
- }
3757
-
3758
- // We've got the timestamp - return all the other unmatched lines as the raw subtitle data
3759
- subtitleParts = subtitleParts.slice(0,subtitlePartIndex).concat(subtitleParts.slice(subtitlePartIndex+1));
3760
- break;
3761
- }
3762
-
3763
- if (!timeIn && !timeOut) {
3764
- // We didn't extract any time information. Assume the cue is invalid!
3765
- return null;
3766
- }
3767
- /*
3768
- // Consolidate cue settings, convert defaults to object
3769
- var compositeCueSettings =
3770
- cueDefaults
3771
- .reduce(function(previous,current,index,array){
3772
- previous[current.split(":")[0]] = current.split(":")[1];
3773
- return previous;
3774
- },{});
3775
-
3776
- // Loop through cue settings, replace defaults with cue specific settings if they exist
3777
- compositeCueSettings =
3778
- cueSettings
3779
- .split(/\s+/g)
3780
- .filter(function(set) { return set && !!set.length; })
3781
- // Convert array to a key/val object
3782
- .reduce(function(previous,current,index,array){
3783
- previous[current.split(":")[0]] = current.split(":")[1];
3784
- return previous;
3785
- },compositeCueSettings);
3786
-
3787
- // Turn back into string like the TextTrackCue constructor expects
3788
- cueSettings = "";
3789
- for (var key in compositeCueSettings) {
3790
- if (compositeCueSettings.hasOwnProperty(key)) {
3791
- cueSettings += !!cueSettings.length ? " " : "";
3792
- cueSettings += key + ":" + compositeCueSettings[key];
3793
- }
3794
- }
3795
- */
3796
- // The remaining lines are the subtitle payload itself (after removing an ID if present, and the time);
3797
- html = subtitleParts.join("\n");
3798
- tmpCue = new TextTrackCue(timeIn, timeOut, html);
3799
- if(id){
3800
- tmpCue.id = id;
3801
- }
3802
- return tmpCue;
3803
- };
3804
- })();
3805
-
3806
- mediaelement.parseCaptions = function(captionData, track, complete) {
3807
- var subtitles = mediaelement.createCueList();
3808
- var cue, lazyProcess, regWevVTT;
3809
- var startDate;
3810
- var isWEBVTT;
3811
- if (captionData) {
3812
-
3813
- regWevVTT = /^WEBVTT(\s*FILE)?/ig;
3814
-
3815
- lazyProcess = function(i, len){
3816
-
3817
- for(; i < len; i++){
3818
- cue = captionData[i];
3819
- if(regWevVTT.test(cue)){
3820
- isWEBVTT = true;
3821
- } else if(cue.replace(/\s*/ig,"").length){
3822
- if(!isWEBVTT){
3823
- webshims.error('please use WebVTT format. This is the standard');
3824
- complete(null);
3825
- break;
3826
- }
3827
- cue = mediaelement.parseCaptionChunk(cue, i);
3828
- if(cue){
3829
- track.addCue(cue);
3830
- }
3831
- }
3832
- if(startDate < (new Date().getTime()) - 9){
3833
- i++;
3834
- setTimeout(function(){
3835
- startDate = new Date().getTime();
3836
- lazyProcess(i, len);
3837
- }, 90);
3838
-
3839
- break;
3840
- }
3841
- }
3842
- if(i >= len){
3843
- if(!isWEBVTT){
3844
- webshims.error('please use WebVTT format. This is the standard');
3845
- }
3846
- complete(track.cues);
3847
- }
3848
- };
3849
-
3850
- captionData = captionData.replace(/\r\n/g,"\n");
3851
-
3852
- setTimeout(function(){
3853
- captionData = captionData.replace(/\r/g,"\n");
3854
- setTimeout(function(){
3855
- startDate = new Date().getTime();
3856
- captionData = captionData.split(/\n\n+/g);
3857
- lazyProcess(0, captionData.length);
3858
- }, 9);
3859
- }, 9);
3860
-
3861
- } else {
3862
- webshims.error("Required parameter captionData not supplied.");
3863
- }
3864
- };
3865
-
3866
-
3867
- mediaelement.createTrackList = function(mediaelem, baseData){
3868
- baseData = baseData || webshims.data(mediaelem, 'mediaelementBase') || webshims.data(mediaelem, 'mediaelementBase', {});
3869
- if(!baseData.textTracks){
3870
- baseData.textTracks = [];
3871
- webshims.defineProperties(baseData.textTracks, {
3872
- onaddtrack: {value: null},
3873
- onremovetrack: {value: null}
3874
- });
3875
- createEventTarget(baseData.textTracks);
3876
- }
3877
- return baseData.textTracks;
3878
- };
3879
-
3880
- if(!Modernizr.track){
3881
- webshims.defineNodeNamesBooleanProperty(['track'], 'default');
3882
- webshims.reflectProperties(['track'], ['srclang', 'label']);
3883
-
3884
- webshims.defineNodeNameProperties('track', {
3885
- src: {
3886
- //attr: {},
3887
- reflect: true,
3888
- propType: 'src'
3889
- }
3890
- });
3891
- }
3892
-
3893
- webshims.defineNodeNameProperties('track', {
3894
- kind: {
3895
- attr: Modernizr.track ? {
3896
- set: function(value){
3897
- var trackData = webshims.data(this, 'trackData');
3898
- this.setAttribute('data-kind', value);
3899
- if(trackData){
3900
- trackData.attrKind = value;
3901
- }
3902
- },
3903
- get: function(){
3904
- var trackData = webshims.data(this, 'trackData');
3905
- if(trackData && ('attrKind' in trackData)){
3906
- return trackData.attrKind;
3907
- }
3908
- return this.getAttribute('kind');
3909
- }
3910
- } : {},
3911
- reflect: true,
3912
- propType: 'enumarated',
3913
- defaultValue: 'subtitles',
3914
- limitedTo: ['subtitles', 'captions', 'descriptions', 'chapters', 'metadata']
3915
- }
3916
- });
3917
-
3918
- webshims.onNodeNamesPropertyModify('track', 'kind', function(){
3919
- var trackData = webshims.data(this, 'trackData');
3920
- if(trackData){
3921
- trackData.track.kind = $.prop(this, 'kind');
3922
- refreshTrack(this, trackData);
3923
- }
3924
- });
3925
-
3926
- webshims.onNodeNamesPropertyModify('track', 'src', function(val){
3927
- if(val){
3928
- var data = webshims.data(this, 'trackData');
3929
- var media;
3930
- if(data){
3931
- media = $(this).closest('video, audio');
3932
- if(media[0]){
3933
- mediaelement.loadTextTrack(media, this, data);
3934
- }
3935
- }
3936
- }
3937
-
3938
- });
3939
-
3940
- //
3941
-
3942
- webshims.defineNodeNamesProperties(['track'], {
3943
- ERROR: {
3944
- value: 3
3945
- },
3946
- LOADED: {
3947
- value: 2
3948
- },
3949
- LOADING: {
3950
- value: 1
3951
- },
3952
- NONE: {
3953
- value: 0
3954
- },
3955
- readyState: {
3956
- get: function(){
3957
- return ($.prop(this, 'track') || {readyState: 0}).readyState;
3958
- },
3959
- writeable: false
3960
- },
3961
- track: {
3962
- get: function(){
3963
- return mediaelement.createTextTrack($(this).closest('audio, video')[0], this);
3964
- },
3965
- writeable: false
3966
- }
3967
- }, 'prop');
3968
-
3969
- webshims.defineNodeNamesProperties(['audio', 'video'], {
3970
- textTracks: {
3971
- get: function(){
3972
-
3973
- var media = this;
3974
- var baseData = webshims.data(media, 'mediaelementBase') || webshims.data(media, 'mediaelementBase', {});
3975
- var tracks = mediaelement.createTrackList(media, baseData);
3976
- if(!baseData.blockTrackListUpdate){
3977
- updateMediaTrackList.call(media, baseData, tracks);
3978
- }
3979
- return tracks;
3980
- },
3981
- writeable: false
3982
- },
3983
- addTextTrack: {
3984
- value: function(kind, label, lang){
3985
- var textTrack = mediaelement.createTextTrack(this, {
3986
- kind: kind || '',
3987
- label: label || '',
3988
- srclang: lang || ''
3989
- });
3990
- var baseData = webshims.data(this, 'mediaelementBase') || webshims.data(this, 'mediaelementBase', {});
3991
- if (!baseData.scriptedTextTracks) {
3992
- baseData.scriptedTextTracks = [];
3993
- }
3994
- baseData.scriptedTextTracks.push(textTrack);
3995
- updateMediaTrackList.call(this);
3996
- return textTrack;
3997
- }
3998
- }
3999
- }, 'prop');
4000
-
4001
-
4002
- $(document).bind('emptied ended updatetracklist', function(e){
4003
- if($(e.target).is('audio, video')){
4004
- var baseData = webshims.data(e.target, 'mediaelementBase');
4005
- if(baseData){
4006
- clearTimeout(baseData.updateTrackListTimer);
4007
- baseData.updateTrackListTimer = setTimeout(function(){
4008
- updateMediaTrackList.call(e.target, baseData);
4009
- }, 0);
4010
- }
4011
- }
4012
- });
4013
-
4014
- var getNativeReadyState = function(trackElem, textTrack){
4015
- return textTrack.readyState || trackElem.readyState;
4016
- };
4017
-
4018
- webshims.addReady(function(context, insertedElement){
4019
- var insertedMedia = insertedElement.filter('video, audio, track').closest('audio, video');
4020
- $('video, audio', context)
4021
- .add(insertedMedia)
4022
- .each(function(){
4023
- updateMediaTrackList.call(this);
4024
- })
4025
- .each(function(){
4026
- if(Modernizr.track){
4027
- var shimedTextTracks = $.prop(this, 'textTracks');
4028
- var origTextTracks = this.textTracks;
4029
- if(shimedTextTracks.length != origTextTracks.length){
4030
- webshims.error("textTracks couldn't be copied");
4031
- }
4032
-
4033
- $('track', this)
4034
- .each(function(){
4035
- var shimedTrack = $.prop(this, 'track');
4036
- var origTrack = this.track;
4037
- var kind;
4038
- var readyState;
4039
- if(origTrack){
4040
- kind = $.prop(this, 'kind');
4041
- readyState = getNativeReadyState(this, origTrack);
4042
- if (origTrack.mode || readyState) {
4043
- shimedTrack.mode = origTrack.mode;
4044
- }
4045
- //disable track from showing + remove UI
4046
- if(kind != 'descriptions'){
4047
- origTrack.mode = (typeof origTrack.mode == 'string') ? 'disabled' : 0;
4048
- this.kind = 'metadata';
4049
- $(this).attr({kind: kind});
4050
- }
4051
-
4052
- }
4053
- })
4054
- .bind('load error', function(e){
4055
- if(e.originalEvent){
4056
- e.stopImmediatePropagation();
4057
- }
4058
- })
4059
- ;
4060
- }
4061
- })
4062
- ;
4063
- insertedMedia.each(function(){
4064
- var media = this;
4065
- var baseData = webshims.data(media, 'mediaelementBase');
4066
- if(baseData){
4067
- clearTimeout(baseData.updateTrackListTimer);
4068
- baseData.updateTrackListTimer = setTimeout(function(){
4069
- updateMediaTrackList.call(media, baseData);
4070
- }, 9);
4071
- }
4072
- });
4073
- });
4074
-
4075
- if(Modernizr.track){
4076
- $('video, audio').trigger('trackapichange');
4077
- }
4078
-
3321
+ });jQuery.webshims.register('track', function($, webshims, window, document, undefined){
3322
+ var mediaelement = webshims.mediaelement;
3323
+ var id = new Date().getTime();
3324
+ //descriptions are not really shown, but they are inserted into the dom
3325
+ var showTracks = {subtitles: 1, captions: 1, descriptions: 1};
3326
+ var notImplemented = function(){
3327
+ webshims.error('not implemented yet');
3328
+ };
3329
+ var supportTrackMod = Modernizr.ES5 && Modernizr.objectAccessor;
3330
+ var createEventTarget = function(obj){
3331
+ var eventList = {};
3332
+ obj.addEventListener = function(name, fn){
3333
+ if(eventList[name]){
3334
+ webshims.error('always use $.bind to the shimed event: '+ name +' already bound fn was: '+ eventList[name] +' your fn was: '+ fn);
3335
+ }
3336
+ eventList[name] = fn;
3337
+
3338
+ };
3339
+ obj.removeEventListener = function(name, fn){
3340
+ if(eventList[name] && eventList[name] != fn){
3341
+ webshims.error('always use $.bind/$.unbind to the shimed event: '+ name +' already bound fn was: '+ eventList[name] +' your fn was: '+ fn);
3342
+ }
3343
+ if(eventList[name]){
3344
+ delete eventList[name];
3345
+ }
3346
+ };
3347
+ return obj;
3348
+ };
3349
+
3350
+
3351
+ var cueListProto = {
3352
+ getCueById: function(id){
3353
+ var cue = null;
3354
+ for(var i = 0, len = this.length; i < len; i++){
3355
+ if(this[i].id === id){
3356
+ cue = this[i];
3357
+ break;
3358
+ }
3359
+ }
3360
+ return cue;
3361
+ }
3362
+ };
3363
+
3364
+ var textTrackProto = {
3365
+ shimActiveCues: null,
3366
+ _shimActiveCues: null,
3367
+ activeCues: null,
3368
+ cues: null,
3369
+ kind: 'subtitles',
3370
+ label: '',
3371
+ language: '',
3372
+ mode: 'disabled',
3373
+ readyState: 0,
3374
+ oncuechange: null,
3375
+ toString: function() {
3376
+ return "[object TextTrack]";
3377
+ },
3378
+ addCue: function(cue){
3379
+ if(!this.cues){
3380
+ this.cues = mediaelement.createCueList();
3381
+ } else {
3382
+ var lastCue = this.cues[this.cues.length-1];
3383
+ if(lastCue && lastCue.startTime > cue.startTime){
3384
+ webshims.error("cue startTime higher than previous cue's startTime");
3385
+ }
3386
+ }
3387
+ if(cue.track && cue.track.removeCue){
3388
+ cue.track.removeCue(cue);
3389
+ }
3390
+ cue.track = this;
3391
+ this.cues.push(cue);
3392
+ },
3393
+ //ToDo: make it more dynamic
3394
+ removeCue: function(cue){
3395
+ var cues = this.cues || [];
3396
+ var i = 0;
3397
+ var len = cues.length;
3398
+ if(cue.track != this){
3399
+ webshims.error("cue not part of track");
3400
+ return;
3401
+ }
3402
+ for(; i < len; i++){
3403
+ if(cues[i] === cue){
3404
+ cues.splice(i, 1);
3405
+ cue.track = null;
3406
+ break;
3407
+ }
3408
+ }
3409
+ if(cue.track){
3410
+ webshims.error("cue not part of track");
3411
+ return;
3412
+ }
3413
+ },
3414
+ DISABLED: 'disabled',
3415
+ OFF: 'disabled',
3416
+ HIDDEN: 'hidden',
3417
+ SHOWING: 'showing',
3418
+ ERROR: 3,
3419
+ LOADED: 2,
3420
+ LOADING: 1,
3421
+ NONE: 0
3422
+ };
3423
+ var copyProps = ['kind', 'label', 'srclang'];
3424
+ var copyName = {srclang: 'language'};
3425
+
3426
+ var owns = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
3427
+
3428
+ var updateMediaTrackList = function(baseData, trackList){
3429
+ var removed = [];
3430
+ var added = [];
3431
+ var newTracks = [];
3432
+ var i, len;
3433
+ if(!baseData){
3434
+ baseData = webshims.data(this, 'mediaelementBase') || webshims.data(this, 'mediaelementBase', {});
3435
+ }
3436
+
3437
+ if(!trackList){
3438
+ baseData.blockTrackListUpdate = true;
3439
+ trackList = $.prop(this, 'textTracks');
3440
+ baseData.blockTrackListUpdate = false;
3441
+ }
3442
+
3443
+ clearTimeout(baseData.updateTrackListTimer);
3444
+
3445
+ $('track', this).each(function(){
3446
+ var track = $.prop(this, 'track');
3447
+ newTracks.push(track);
3448
+ if(trackList.indexOf(track) == -1){
3449
+ added.push(track);
3450
+ }
3451
+ });
3452
+
3453
+ if(baseData.scriptedTextTracks){
3454
+ for(i = 0, len = baseData.scriptedTextTracks.length; i < len; i++){
3455
+ newTracks.push(baseData.scriptedTextTracks[i]);
3456
+ if(trackList.indexOf(baseData.scriptedTextTracks[i]) == -1){
3457
+ added.push(baseData.scriptedTextTracks[i]);
3458
+ }
3459
+ }
3460
+ }
3461
+
3462
+ for(i = 0, len = trackList.length; i < len; i++){
3463
+ if(newTracks.indexOf(trackList[i]) == -1){
3464
+ removed.push(trackList[i]);
3465
+ }
3466
+ }
3467
+
3468
+ if(removed.length || added.length){
3469
+ trackList.splice(0);
3470
+
3471
+ for(i = 0, len = newTracks.length; i < len; i++){
3472
+ trackList.push(newTracks[i]);
3473
+ }
3474
+ for(i = 0, len = removed.length; i < len; i++){
3475
+ $([trackList]).triggerHandler($.Event({type: 'removetrack', track: trackList, track: removed[i]}));
3476
+ }
3477
+ for(i = 0, len = added.length; i < len; i++){
3478
+ $([trackList]).triggerHandler($.Event({type: 'addtrack', track: trackList, track: added[i]}));
3479
+ }
3480
+ if(baseData.scriptedTextTracks || removed.length){
3481
+ $(this).triggerHandler('updatetrackdisplay');
3482
+ }
3483
+ }
3484
+ };
3485
+
3486
+ var refreshTrack = function(track, trackData){
3487
+ if(!trackData){
3488
+ trackData = webshims.data(track, 'trackData');
3489
+ }
3490
+ if(trackData && !trackData.isTriggering){
3491
+ trackData.isTriggering = true;
3492
+ setTimeout(function(){
3493
+ if(!(trackData.track || {}).readyState){
3494
+ $(track).triggerHandler('checktrackmode');
3495
+ } else {
3496
+ $(track).closest('audio, video').triggerHandler('updatetrackdisplay');
3497
+ }
3498
+ trackData.isTriggering = false;
3499
+ }, 1);
3500
+ }
3501
+ };
3502
+
3503
+ var emptyDiv = $('<div />')[0];
3504
+ window.TextTrackCue = function(startTime, endTime, text){
3505
+ if(arguments.length != 3){
3506
+ webshims.error("wrong arguments.length for TextTrackCue.constructor");
3507
+ }
3508
+
3509
+ this.startTime = startTime;
3510
+ this.endTime = endTime;
3511
+ this.text = text;
3512
+
3513
+ this.id = "";
3514
+ this.pauseOnExit = false;
3515
+
3516
+ createEventTarget(this);
3517
+ };
3518
+
3519
+ window.TextTrackCue.prototype = {
3520
+
3521
+ onenter: null,
3522
+ onexit: null,
3523
+ pauseOnExit: false,
3524
+ getCueAsHTML: function(){
3525
+ var lastText = "";
3526
+ var parsedText = "";
3527
+ var fragment = document.createDocumentFragment();
3528
+ var fn;
3529
+ if(!owns(this, 'getCueAsHTML')){
3530
+ fn = this.getCueAsHTML = function(){
3531
+ var i, len;
3532
+ if(lastText != this.text){
3533
+ lastText = this.text;
3534
+ parsedText = mediaelement.parseCueTextToHTML(lastText);
3535
+ emptyDiv.innerHTML = parsedText;
3536
+
3537
+ for(i = 0, len = emptyDiv.childNodes.length; i < len; i++){
3538
+ fragment.appendChild(emptyDiv.childNodes[i].cloneNode(true));
3539
+ }
3540
+ }
3541
+ return fragment.cloneNode(true);
3542
+ };
3543
+
3544
+ }
3545
+ return fn ? fn.apply(this, arguments) : fragment.cloneNode(true);
3546
+ },
3547
+ track: null,
3548
+
3549
+
3550
+ id: ''
3551
+ //todo-->
3552
+ // ,
3553
+ // snapToLines: true,
3554
+ // line: 'auto',
3555
+ // size: 100,
3556
+ // position: 50,
3557
+ // vertical: '',
3558
+ // align: 'middle'
3559
+ };
3560
+
3561
+
3562
+
3563
+
3564
+
3565
+ mediaelement.createCueList = function(){
3566
+ return $.extend([], cueListProto);
3567
+ };
3568
+
3569
+ mediaelement.parseCueTextToHTML = (function(){
3570
+ var tagSplits = /(<\/?[^>]+>)/ig;
3571
+ var allowedTags = /^(?:c|v|ruby|rt|b|i|u)/;
3572
+ var regEnd = /\<\s*\//;
3573
+ var addToTemplate = function(localName, attribute, tag, html){
3574
+ var ret;
3575
+ if(regEnd.test(html)){
3576
+ ret = '</'+ localName +'>';
3577
+ } else {
3578
+ tag.splice(0, 1);
3579
+ ret = '<'+ localName +' '+ attribute +'="'+ (tag.join(' ').replace(/\"/g, '&#34;')) +'">';
3580
+ }
3581
+ return ret;
3582
+ };
3583
+ var replacer = function(html){
3584
+ var tag = html.replace(/[<\/>]+/ig,"").split(/[\s\.]+/);
3585
+ if(tag[0]){
3586
+ tag[0] = tag[0].toLowerCase();
3587
+ if(allowedTags.test(tag[0])){
3588
+ if(tag[0] == 'c'){
3589
+ html = addToTemplate('span', 'class', tag, html);
3590
+ } else if(tag[0] == 'v'){
3591
+ html = addToTemplate('q', 'title', tag, html);
3592
+ }
3593
+ } else {
3594
+ html = "";
3595
+ }
3596
+ }
3597
+ return html;
3598
+ };
3599
+
3600
+ return function(cueText){
3601
+ return cueText.replace(tagSplits, replacer);
3602
+ };
3603
+ })();
3604
+
3605
+ mediaelement.loadTextTrack = function(mediaelem, track, trackData, _default){
3606
+ var loadEvents = 'play playing timeupdate updatetrackdisplay';
3607
+ var obj = trackData.track;
3608
+ var load = function(){
3609
+ var src = $.prop(track, 'src');
3610
+ var error;
3611
+ var ajax;
3612
+ if(obj.mode != 'disabled' && src && $.attr(track, 'src')){
3613
+ $(mediaelem).unbind(loadEvents, load);
3614
+ $(track).unbind('checktrackmode', load);
3615
+ if(!obj.readyState){
3616
+ error = function(){
3617
+ obj.readyState = 3;
3618
+ obj.cues = null;
3619
+ obj.activeCues = obj.shimActiveCues = obj._shimActiveCues = null;
3620
+ $(track).triggerHandler('error');
3621
+ };
3622
+ obj.readyState = 1;
3623
+ try {
3624
+ obj.cues = mediaelement.createCueList();
3625
+ obj.activeCues = obj.shimActiveCues = obj._shimActiveCues = mediaelement.createCueList();
3626
+ ajax = $.ajax({
3627
+ dataType: 'text',
3628
+ url: src,
3629
+ success: function(text){
3630
+ if(ajax.getResponseHeader('content-type') != 'text/vtt'){
3631
+ webshims.error('set the mime-type of your WebVTT files to text/vtt. see: http://dev.w3.org/html5/webvtt/#text/vtt');
3632
+ }
3633
+ mediaelement.parseCaptions(text, obj, function(cues){
3634
+ if(cues && 'length' in cues){
3635
+ obj.readyState = 2;
3636
+ $(track).triggerHandler('load');
3637
+ $(mediaelem).triggerHandler('updatetrackdisplay');
3638
+ } else {
3639
+ error();
3640
+ }
3641
+ });
3642
+
3643
+ },
3644
+ error: error
3645
+ });
3646
+ } catch(er){
3647
+ error();
3648
+ webshims.warn(er);
3649
+ }
3650
+ }
3651
+ }
3652
+ };
3653
+ obj.readyState = 0;
3654
+ obj.shimActiveCues = null;
3655
+ obj._shimActiveCues = null;
3656
+ obj.activeCues = null;
3657
+ obj.cues = null;
3658
+ $(mediaelem).unbind(loadEvents, load);
3659
+ $(track).unbind('checktrackmode', load);
3660
+ $(mediaelem).bind(loadEvents, load);
3661
+ $(track).bind('checktrackmode', load);
3662
+ if(_default){
3663
+ obj.mode = showTracks[obj.kind] ? 'showing' : 'hidden';
3664
+ load();
3665
+ }
3666
+ };
3667
+
3668
+ mediaelement.createTextTrack = function(mediaelem, track){
3669
+ var obj, trackData;
3670
+ if(track.nodeName){
3671
+ trackData = webshims.data(track, 'trackData');
3672
+
3673
+ if(trackData){
3674
+ refreshTrack(track, trackData);
3675
+ obj = trackData.track;
3676
+ }
3677
+ }
3678
+
3679
+ if(!obj){
3680
+ obj = createEventTarget(webshims.objectCreate(textTrackProto));
3681
+
3682
+ if(!supportTrackMod){
3683
+ copyProps.forEach(function(copyProp){
3684
+ var prop = $.prop(track, copyProp);
3685
+ if(prop){
3686
+ obj[copyName[copyProp] || copyProp] = prop;
3687
+ }
3688
+ });
3689
+ }
3690
+
3691
+
3692
+ if(track.nodeName){
3693
+
3694
+ if(supportTrackMod){
3695
+ copyProps.forEach(function(copyProp){
3696
+ webshims.defineProperty(obj, copyName[copyProp] || copyProp, {
3697
+ get: function(){
3698
+ return $.prop(track, copyProp);
3699
+ }
3700
+ });
3701
+ });
3702
+ }
3703
+
3704
+ trackData = webshims.data(track, 'trackData', {track: obj});
3705
+ mediaelement.loadTextTrack(mediaelem, track, trackData, ($.prop(track, 'default') && $(track).siblings('track[default]').andSelf()[0] == track));
3706
+ } else {
3707
+ if(supportTrackMod){
3708
+ copyProps.forEach(function(copyProp){
3709
+ webshims.defineProperty(obj, copyName[copyProp] || copyProp, {
3710
+ value: track[copyProp],
3711
+ writeable: false
3712
+ });
3713
+ });
3714
+ }
3715
+ obj.cues = mediaelement.createCueList();
3716
+ obj.activeCues = obj._shimActiveCues = obj.shimActiveCues = mediaelement.createCueList();
3717
+ obj.mode = 'hidden';
3718
+ obj.readyState = 2;
3719
+ }
3720
+ }
3721
+ return obj;
3722
+ };
3723
+
3724
+
3725
+ /*
3726
+ taken from:
3727
+ Captionator 0.5.1 [CaptionCrunch]
3728
+ Christopher Giffard, 2011
3729
+ Share and enjoy
3730
+
3731
+ https://github.com/cgiffard/Captionator
3732
+
3733
+ modified for webshims
3734
+ */
3735
+ mediaelement.parseCaptionChunk = (function(){
3736
+ // Set up timestamp parsers
3737
+ var WebVTTTimestampParser = /^(\d{2})?:?(\d{2}):(\d{2})\.(\d+)\s+\-\-\>\s+(\d{2})?:?(\d{2}):(\d{2})\.(\d+)\s*(.*)/;
3738
+ var GoogleTimestampParser = /^([\d\.]+)\s+\+([\d\.]+)\s*(.*)/;
3739
+ var WebVTTDEFAULTSCueParser = /^(DEFAULTS|DEFAULT)\s+\-\-\>\s+(.*)/g;
3740
+ var WebVTTSTYLECueParser = /^(STYLE|STYLES)\s+\-\-\>\s*\n([\s\S]*)/g;
3741
+ var WebVTTCOMMENTCueParser = /^(COMMENT|COMMENTS)\s+\-\-\>\s+(.*)/g;
3742
+
3743
+ return function(subtitleElement,objectCount){
3744
+ var cueDefaults = [];
3745
+
3746
+ var subtitleParts, timeIn, timeOut, html, timeData, subtitlePartIndex, cueSettings = "", id, specialCueData;
3747
+ var timestampMatch, tmpCue;
3748
+
3749
+ // WebVTT Special Cue Logic
3750
+ if ((specialCueData = WebVTTDEFAULTSCueParser.exec(subtitleElement))) {
3751
+ // cueDefaults = specialCueData.slice(2).join("");
3752
+ // cueDefaults = cueDefaults.split(/\s+/g).filter(function(def) { return def && !!def.length; });
3753
+ return null;
3754
+ } else if ((specialCueData = WebVTTSTYLECueParser.exec(subtitleElement))) {
3755
+ return null;
3756
+ } else if ((specialCueData = WebVTTCOMMENTCueParser.exec(subtitleElement))) {
3757
+ return null; // At this stage, we don't want to do anything with these.
3758
+ }
3759
+
3760
+ subtitleParts = subtitleElement.split(/\n/g);
3761
+
3762
+ // Trim off any blank lines (logically, should only be max. one, but loop to be sure)
3763
+ while (!subtitleParts[0].replace(/\s+/ig,"").length && subtitleParts.length > 0) {
3764
+ subtitleParts.shift();
3765
+ }
3766
+
3767
+ if (subtitleParts[0].match(/^\s*[a-z0-9-\_]+\s*$/ig)) {
3768
+ // The identifier becomes the cue ID (when *we* load the cues from file. Programatically created cues can have an ID of whatever.)
3769
+ id = String(subtitleParts.shift().replace(/\s*/ig,""));
3770
+ }
3771
+
3772
+ for (subtitlePartIndex = 0; subtitlePartIndex < subtitleParts.length; subtitlePartIndex ++) {
3773
+ var timestamp = subtitleParts[subtitlePartIndex];
3774
+
3775
+ if ((timestampMatch = WebVTTTimestampParser.exec(timestamp))) {
3776
+
3777
+ // WebVTT
3778
+
3779
+ timeData = timestampMatch.slice(1);
3780
+
3781
+ timeIn = parseInt((timeData[0]||0) * 60 * 60,10) + // Hours
3782
+ parseInt((timeData[1]||0) * 60,10) + // Minutes
3783
+ parseInt((timeData[2]||0),10) + // Seconds
3784
+ parseFloat("0." + (timeData[3]||0)); // MS
3785
+
3786
+ timeOut = parseInt((timeData[4]||0) * 60 * 60,10) + // Hours
3787
+ parseInt((timeData[5]||0) * 60,10) + // Minutes
3788
+ parseInt((timeData[6]||0),10) + // Seconds
3789
+ parseFloat("0." + (timeData[7]||0)); // MS
3790
+ /*
3791
+ if (timeData[8]) {
3792
+ cueSettings = timeData[8];
3793
+ }
3794
+ */
3795
+ }
3796
+
3797
+ // We've got the timestamp - return all the other unmatched lines as the raw subtitle data
3798
+ subtitleParts = subtitleParts.slice(0,subtitlePartIndex).concat(subtitleParts.slice(subtitlePartIndex+1));
3799
+ break;
3800
+ }
3801
+
3802
+ if (!timeIn && !timeOut) {
3803
+ // We didn't extract any time information. Assume the cue is invalid!
3804
+ webshims.warn("couldn't extract time information: "+[timeIn, timeOut, subtitleParts.join("\n"), id].join(' ; '));
3805
+ return null;
3806
+ }
3807
+ /*
3808
+ // Consolidate cue settings, convert defaults to object
3809
+ var compositeCueSettings =
3810
+ cueDefaults
3811
+ .reduce(function(previous,current,index,array){
3812
+ previous[current.split(":")[0]] = current.split(":")[1];
3813
+ return previous;
3814
+ },{});
3815
+
3816
+ // Loop through cue settings, replace defaults with cue specific settings if they exist
3817
+ compositeCueSettings =
3818
+ cueSettings
3819
+ .split(/\s+/g)
3820
+ .filter(function(set) { return set && !!set.length; })
3821
+ // Convert array to a key/val object
3822
+ .reduce(function(previous,current,index,array){
3823
+ previous[current.split(":")[0]] = current.split(":")[1];
3824
+ return previous;
3825
+ },compositeCueSettings);
3826
+
3827
+ // Turn back into string like the TextTrackCue constructor expects
3828
+ cueSettings = "";
3829
+ for (var key in compositeCueSettings) {
3830
+ if (compositeCueSettings.hasOwnProperty(key)) {
3831
+ cueSettings += !!cueSettings.length ? " " : "";
3832
+ cueSettings += key + ":" + compositeCueSettings[key];
3833
+ }
3834
+ }
3835
+ */
3836
+ // The remaining lines are the subtitle payload itself (after removing an ID if present, and the time);
3837
+ html = subtitleParts.join("\n");
3838
+ tmpCue = new TextTrackCue(timeIn, timeOut, html);
3839
+ if(id){
3840
+ tmpCue.id = id;
3841
+ }
3842
+ return tmpCue;
3843
+ };
3844
+ })();
3845
+
3846
+ mediaelement.parseCaptions = function(captionData, track, complete) {
3847
+ var subtitles = mediaelement.createCueList();
3848
+ var cue, lazyProcess, regWevVTT;
3849
+ var startDate;
3850
+ var isWEBVTT;
3851
+ if (captionData) {
3852
+
3853
+ regWevVTT = /^WEBVTT(\s*FILE)?/ig;
3854
+
3855
+ lazyProcess = function(i, len){
3856
+
3857
+ for(; i < len; i++){
3858
+ cue = captionData[i];
3859
+ if(regWevVTT.test(cue)){
3860
+ isWEBVTT = true;
3861
+ } else if(cue.replace(/\s*/ig,"").length){
3862
+ if(!isWEBVTT){
3863
+ webshims.error('please use WebVTT format. This is the standard');
3864
+ complete(null);
3865
+ break;
3866
+ }
3867
+ cue = mediaelement.parseCaptionChunk(cue, i);
3868
+ if(cue){
3869
+ track.addCue(cue);
3870
+ }
3871
+ }
3872
+ if(startDate < (new Date().getTime()) - 30){
3873
+ i++;
3874
+ setTimeout(function(){
3875
+ startDate = new Date().getTime();
3876
+ lazyProcess(i, len);
3877
+ }, 90);
3878
+
3879
+ break;
3880
+ }
3881
+ }
3882
+ if(i >= len){
3883
+ if(!isWEBVTT){
3884
+ webshims.error('please use WebVTT format. This is the standard');
3885
+ }
3886
+ complete(track.cues);
3887
+ }
3888
+ };
3889
+
3890
+ captionData = captionData.replace(/\r\n/g,"\n");
3891
+
3892
+ setTimeout(function(){
3893
+ captionData = captionData.replace(/\r/g,"\n");
3894
+ setTimeout(function(){
3895
+ startDate = new Date().getTime();
3896
+ captionData = captionData.split(/\n\n+/g);
3897
+ lazyProcess(0, captionData.length);
3898
+ }, 9);
3899
+ }, 9);
3900
+
3901
+ } else {
3902
+ webshims.error("Required parameter captionData not supplied.");
3903
+ }
3904
+ };
3905
+
3906
+
3907
+ mediaelement.createTrackList = function(mediaelem, baseData){
3908
+ baseData = baseData || webshims.data(mediaelem, 'mediaelementBase') || webshims.data(mediaelem, 'mediaelementBase', {});
3909
+ if(!baseData.textTracks){
3910
+ baseData.textTracks = [];
3911
+ webshims.defineProperties(baseData.textTracks, {
3912
+ onaddtrack: {value: null},
3913
+ onremovetrack: {value: null}
3914
+ });
3915
+ createEventTarget(baseData.textTracks);
3916
+ }
3917
+ return baseData.textTracks;
3918
+ };
3919
+
3920
+ if(!Modernizr.track){
3921
+ webshims.defineNodeNamesBooleanProperty(['track'], 'default');
3922
+ webshims.reflectProperties(['track'], ['srclang', 'label']);
3923
+
3924
+ webshims.defineNodeNameProperties('track', {
3925
+ src: {
3926
+ //attr: {},
3927
+ reflect: true,
3928
+ propType: 'src'
3929
+ }
3930
+ });
3931
+ }
3932
+
3933
+ webshims.defineNodeNameProperties('track', {
3934
+ kind: {
3935
+ attr: Modernizr.track ? {
3936
+ set: function(value){
3937
+ var trackData = webshims.data(this, 'trackData');
3938
+ this.setAttribute('data-kind', value);
3939
+ if(trackData){
3940
+ trackData.attrKind = value;
3941
+ }
3942
+ },
3943
+ get: function(){
3944
+ var trackData = webshims.data(this, 'trackData');
3945
+ if(trackData && ('attrKind' in trackData)){
3946
+ return trackData.attrKind;
3947
+ }
3948
+ return this.getAttribute('kind');
3949
+ }
3950
+ } : {},
3951
+ reflect: true,
3952
+ propType: 'enumarated',
3953
+ defaultValue: 'subtitles',
3954
+ limitedTo: ['subtitles', 'captions', 'descriptions', 'chapters', 'metadata']
3955
+ }
3956
+ });
3957
+
3958
+ $.each(copyProps, function(i, copyProp){
3959
+ var name = copyName[copyProp] || copyProp;
3960
+ webshims.onNodeNamesPropertyModify('track', copyProp, function(){
3961
+ var trackData = webshims.data(this, 'trackData');
3962
+ var track = this;
3963
+ if(trackData){
3964
+ if(copyProp == 'kind'){
3965
+ refreshTrack(this, trackData);
3966
+ }
3967
+ if(!supportTrackMod){
3968
+ trackData.track[name] = $.prop(this, copyProp);
3969
+ }
3970
+ clearTimeout(trackData.changedTrackPropTimer);
3971
+ trackData.changedTrackPropTimer = setTimeout(function(){
3972
+ $(track).trigger('updatesubtitlestate');
3973
+ }, 1);
3974
+ }
3975
+ });
3976
+ });
3977
+
3978
+
3979
+ webshims.onNodeNamesPropertyModify('track', 'src', function(val){
3980
+ if(val){
3981
+ var data = webshims.data(this, 'trackData');
3982
+ var media;
3983
+ if(data){
3984
+ media = $(this).closest('video, audio');
3985
+ if(media[0]){
3986
+ mediaelement.loadTextTrack(media, this, data);
3987
+ }
3988
+ }
3989
+ }
3990
+
3991
+ });
3992
+
3993
+ //
3994
+
3995
+ webshims.defineNodeNamesProperties(['track'], {
3996
+ ERROR: {
3997
+ value: 3
3998
+ },
3999
+ LOADED: {
4000
+ value: 2
4001
+ },
4002
+ LOADING: {
4003
+ value: 1
4004
+ },
4005
+ NONE: {
4006
+ value: 0
4007
+ },
4008
+ readyState: {
4009
+ get: function(){
4010
+ return ($.prop(this, 'track') || {readyState: 0}).readyState;
4011
+ },
4012
+ writeable: false
4013
+ },
4014
+ track: {
4015
+ get: function(){
4016
+ return mediaelement.createTextTrack($(this).closest('audio, video')[0], this);
4017
+ },
4018
+ writeable: false
4019
+ }
4020
+ }, 'prop');
4021
+
4022
+ webshims.defineNodeNamesProperties(['audio', 'video'], {
4023
+ textTracks: {
4024
+ get: function(){
4025
+ var media = this;
4026
+ var baseData = webshims.data(media, 'mediaelementBase') || webshims.data(media, 'mediaelementBase', {});
4027
+ var tracks = mediaelement.createTrackList(media, baseData);
4028
+ if(!baseData.blockTrackListUpdate){
4029
+ updateMediaTrackList.call(media, baseData, tracks);
4030
+ }
4031
+ return tracks;
4032
+ },
4033
+ writeable: false
4034
+ },
4035
+ addTextTrack: {
4036
+ value: function(kind, label, lang){
4037
+ var textTrack = mediaelement.createTextTrack(this, {
4038
+ kind: kind || '',
4039
+ label: label || '',
4040
+ srclang: lang || ''
4041
+ });
4042
+ var baseData = webshims.data(this, 'mediaelementBase') || webshims.data(this, 'mediaelementBase', {});
4043
+ if (!baseData.scriptedTextTracks) {
4044
+ baseData.scriptedTextTracks = [];
4045
+ }
4046
+ baseData.scriptedTextTracks.push(textTrack);
4047
+ updateMediaTrackList.call(this);
4048
+ return textTrack;
4049
+ }
4050
+ }
4051
+ }, 'prop');
4052
+
4053
+
4054
+ $(document).bind('emptied ended updatetracklist', function(e){
4055
+ if($(e.target).is('audio, video')){
4056
+ var baseData = webshims.data(e.target, 'mediaelementBase');
4057
+ if(baseData){
4058
+ clearTimeout(baseData.updateTrackListTimer);
4059
+ baseData.updateTrackListTimer = setTimeout(function(){
4060
+ updateMediaTrackList.call(e.target, baseData);
4061
+ }, 0);
4062
+ }
4063
+ }
4064
+ });
4065
+
4066
+ var getNativeReadyState = function(trackElem, textTrack){
4067
+ return textTrack.readyState || trackElem.readyState;
4068
+ };
4069
+
4070
+ webshims.addReady(function(context, insertedElement){
4071
+ var insertedMedia = insertedElement.filter('video, audio, track').closest('audio, video');
4072
+ $('video, audio', context)
4073
+ .add(insertedMedia)
4074
+ .each(function(){
4075
+ updateMediaTrackList.call(this);
4076
+ })
4077
+ .each(function(){
4078
+ if(Modernizr.track){
4079
+ var shimedTextTracks = $.prop(this, 'textTracks');
4080
+ var origTextTracks = this.textTracks;
4081
+ if(shimedTextTracks.length != origTextTracks.length){
4082
+ webshims.error("textTracks couldn't be copied");
4083
+ }
4084
+
4085
+ $('track', this)
4086
+ .each(function(){
4087
+ var shimedTrack = $.prop(this, 'track');
4088
+ var origTrack = this.track;
4089
+ var kind;
4090
+ var readyState;
4091
+ if(origTrack){
4092
+ kind = $.prop(this, 'kind');
4093
+ readyState = getNativeReadyState(this, origTrack);
4094
+ if (origTrack.mode || readyState) {
4095
+ shimedTrack.mode = origTrack.mode;
4096
+ }
4097
+ //disable track from showing + remove UI
4098
+ if(kind != 'descriptions'){
4099
+ origTrack.mode = (typeof origTrack.mode == 'string') ? 'disabled' : 0;
4100
+ this.kind = 'metadata';
4101
+ $(this).attr({kind: kind});
4102
+ }
4103
+
4104
+ }
4105
+ })
4106
+ .bind('load error', function(e){
4107
+ if(e.originalEvent){
4108
+ e.stopImmediatePropagation();
4109
+ }
4110
+ })
4111
+ ;
4112
+ }
4113
+ })
4114
+ ;
4115
+ insertedMedia.each(function(){
4116
+ var media = this;
4117
+ var baseData = webshims.data(media, 'mediaelementBase');
4118
+ if(baseData){
4119
+ clearTimeout(baseData.updateTrackListTimer);
4120
+ baseData.updateTrackListTimer = setTimeout(function(){
4121
+ updateMediaTrackList.call(media, baseData);
4122
+ }, 9);
4123
+ }
4124
+ });
4125
+ });
4126
+
4127
+ if(Modernizr.track){
4128
+ $('video, audio').trigger('trackapichange');
4129
+ }
4130
+
4079
4131
  });