webshims-rails 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
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
  });