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
@@ -388,7 +388,7 @@ jQuery.webshims.register('dom-extend', function($, webshims, window, document, u
388
388
  var docObserve = {
389
389
  init: false,
390
390
  start: function(){
391
- if(!this.init){
391
+ if(!this.init && document.body){
392
392
  this.init = true;
393
393
  this.height = $(document).height();
394
394
  this.width = $(document).width();
@@ -400,7 +400,7 @@ jQuery.webshims.register('dom-extend', function($, webshims, window, document, u
400
400
  docObserve.width = width;
401
401
  handler({type: 'docresize'});
402
402
  }
403
- }, 400);
403
+ }, 600);
404
404
  }
405
405
  }
406
406
  };
@@ -416,8 +416,10 @@ jQuery.webshims.register('dom-extend', function($, webshims, window, document, u
416
416
  }
417
417
  lastHeight = height;
418
418
  lastWidth = width;
419
- docObserve.height = $(document).height();
420
- docObserve.width = $(document).width();
419
+ if(document.body){
420
+ docObserve.height = $(document).height();
421
+ docObserve.width = $(document).width();
422
+ }
421
423
  }
422
424
  $.event.trigger('updateshadowdom');
423
425
  }, 40);
@@ -463,7 +465,9 @@ jQuery.webshims.register('dom-extend', function($, webshims, window, document, u
463
465
  shadowFocusElementData.shadowData.data = shadowData.shadowData.data = nativeData.shadowData.data = opts.data;
464
466
  }
465
467
  opts = null;
466
- docObserve.start();
468
+ webshims.ready('DOM', function(){
469
+ docObserve.start();
470
+ });
467
471
  }
468
472
  })(),
469
473
  propTypes: {
@@ -607,7 +611,7 @@ jQuery.webshims.register('dom-extend', function($, webshims, window, document, u
607
611
  }
608
612
  if(propType){
609
613
  if(descs[prop][propType]){
610
- webshims.log('override: '+ name +'['+prop +'] for '+ propType);
614
+ //webshims.log('override: '+ name +'['+prop +'] for '+ propType);
611
615
  } else {
612
616
  descs[prop][propType] = {};
613
617
  ['value', 'set', 'get'].forEach(function(copyProp){
@@ -1439,766 +1443,814 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u
1439
1443
  });
1440
1444
 
1441
1445
  });
1442
- })(jQuery, Modernizr, jQuery.webshims);jQuery.webshims.register('track', function($, webshims, window, document, undefined){
1443
- var mediaelement = webshims.mediaelement;
1444
- var id = new Date().getTime();
1445
- var showTracks = {subtitles: 1, captions: 1};
1446
- var notImplemented = function(){
1447
- webshims.error('not implemented yet');
1448
- };
1449
-
1450
- var createEventTarget = function(obj){
1451
- var eventList = {};
1452
- obj.addEventListener = function(name, fn){
1453
- if(eventList[name]){
1454
- webshims.error('always use $.bind to the shimed event: '+ name +' already bound fn was: '+ eventList[name] +' your fn was: '+ fn);
1455
- }
1456
- eventList[name] = fn;
1457
-
1458
- };
1459
- obj.removeEventListener = function(name, fn){
1460
- if(eventList[name] && eventList[name] != fn){
1461
- webshims.error('always use $.bind/$.unbind to the shimed event: '+ name +' already bound fn was: '+ eventList[name] +' your fn was: '+ fn);
1462
- }
1463
- if(eventList[name]){
1464
- delete eventList[name];
1465
- }
1466
- };
1467
- return obj;
1468
- };
1469
-
1470
-
1471
- var cueListProto = {
1472
- getCueById: function(id){
1473
- var cue = null;
1474
- for(var i = 0, len = this.length; i < len; i++){
1475
- if(this[i].id === id){
1476
- cue = this[i];
1477
- break;
1478
- }
1479
- }
1480
- return cue;
1481
- }
1482
- };
1483
- var textTrackProto = {
1484
- shimActiveCues: null,
1485
- _shimActiveCues: null,
1486
- activeCues: null,
1487
- cues: null,
1488
- kind: 'subtitles',
1489
- label: '',
1490
- language: '',
1491
- mode: 'disabled',
1492
- readyState: 0,
1493
- oncuechange: null,
1494
- toString: function() {
1495
- return "[object TextTrack]";
1496
- },
1497
- addCue: function(cue){
1498
- if(!this.cues){
1499
- this.cues = mediaelement.createCueList();
1500
- } else {
1501
- var lastCue = this.cues[this.cues.length-1];
1502
- if(lastCue && lastCue.startTime > cue.startTime){
1503
- webshims.error("cue startTime higher than previous cue's startTime");
1504
- }
1505
- }
1506
- if(cue.track){
1507
- webshims.error("cue already part of a track element");
1508
- }
1509
- cue.track = this;
1510
- this.cues.push(cue);
1511
- },
1512
- removeCue: notImplemented,
1513
- DISABLED: 'disabled',
1514
- OFF: 'disabled',
1515
- HIDDEN: 'hidden',
1516
- SHOWING: 'showing',
1517
- ERROR: 3,
1518
- LOADED: 2,
1519
- LOADING: 1,
1520
- NONE: 0
1521
- };
1522
- var copyProps = ['kind', 'label', 'srclang'];
1523
-
1524
- var owns = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
1525
-
1526
- //ToDo: add/remove event
1527
- var updateMediaTrackList = function(baseData, trackList){
1528
- var removed = [];
1529
- var added = [];
1530
- var newTracks = [];
1531
- var i, len;
1532
- if(!baseData){
1533
- baseData = webshims.data(this, 'mediaelementBase') || webshims.data(this, 'mediaelementBase', {});
1534
- }
1535
-
1536
- if(!trackList){
1537
- baseData.blockTrackListUpdate = true;
1538
- trackList = $.prop(this, 'textTracks');
1539
- baseData.blockTrackListUpdate = false;
1540
- }
1541
-
1542
- clearTimeout(baseData.updateTrackListTimer);
1543
-
1544
- $('track', this).each(function(){
1545
- var track = $.prop(this, 'track');
1546
- newTracks.push(track);
1547
- if(trackList.indexOf(track) == -1){
1548
- added.push(track);
1549
- }
1550
- });
1551
-
1552
- if(baseData.scriptedTextTracks){
1553
- for(i = 0, len = baseData.scriptedTextTracks.length; i < len; i++){
1554
- newTracks.push(baseData.scriptedTextTracks[i]);
1555
- if(trackList.indexOf(baseData.scriptedTextTracks[i]) == -1){
1556
- added.push(baseData.scriptedTextTracks[i]);
1557
- }
1558
- }
1559
- }
1560
-
1561
- for(i = 0, len = trackList.length; i < len; i++){
1562
- if(newTracks.indexOf(trackList[i]) == -1){
1563
- removed.push(trackList[i]);
1564
- }
1565
- }
1566
-
1567
- if(removed.length || added.length){
1568
- trackList.splice(0);
1569
-
1570
- for(i = 0, len = newTracks.length; i < len; i++){
1571
- trackList.push(newTracks[i]);
1572
- }
1573
- for(i = 0, len = removed.length; i < len; i++){
1574
- $([trackList]).triggerHandler($.Event({type: 'removetrack', track: trackList, track: removed[i]}));
1575
- }
1576
- for(i = 0, len = added.length; i < len; i++){
1577
- $([trackList]).triggerHandler($.Event({type: 'addtrack', track: trackList, track: added[i]}));
1578
- }
1579
- if(baseData.scriptedTextTracks || removed.length){
1580
- $(this).triggerHandler('updatetrackdisplay');
1581
- }
1582
- }
1583
- };
1584
-
1585
- var refreshTrack = function(track, trackData){
1586
- var mode, kind;
1587
- if(!trackData){
1588
- trackData = webshims.data(track, 'trackData');
1589
- }
1590
- if(trackData && !trackData.isTriggering){
1591
- trackData.isTriggering = true;
1592
- mode = (trackData.track || {}).mode;
1593
- kind = (trackData.track || {}).kind;
1594
- setTimeout(function(){
1595
- if(mode !== (trackData.track || {}).mode || kind != (trackData.track || {}).kind){
1596
- if(!(trackData.track || {}).readyState){
1597
- $(track).triggerHandler('checktrackmode');
1598
- } else {
1599
- $(track).parent().triggerHandler('updatetrackdisplay');
1600
- }
1601
- }
1602
- trackData.isTriggering = false;
1603
-
1604
- }, 9);
1605
- }
1606
- };
1607
-
1608
- var emptyDiv = $('<div />')[0];
1609
- window.TextTrackCue = function(startTime, endTime, text){
1610
- if(arguments.length != 3){
1611
- webshims.error("wrong arguments.length for TextTrackCue.constructor");
1612
- }
1613
-
1614
- this.startTime = startTime;
1615
- this.endTime = endTime;
1616
- this.text = text;
1617
-
1618
- this.id = "";
1619
- this.pauseOnExit = false;
1620
-
1621
- createEventTarget(this);
1622
- };
1623
-
1624
- window.TextTrackCue.prototype = {
1625
-
1626
- onenter: null,
1627
- onexit: null,
1628
- pauseOnExit: false,
1629
- getCueAsHTML: function(){
1630
- var lastText = "";
1631
- var parsedText = "";
1632
- var fragment = document.createDocumentFragment();
1633
- var fn;
1634
- if(!owns(this, 'getCueAsHTML')){
1635
- fn = this.getCueAsHTML = function(){
1636
- var i, len;
1637
- if(lastText != this.text){
1638
- lastText = this.text;
1639
- parsedText = mediaelement.parseCueTextToHTML(lastText);
1640
- emptyDiv.innerHTML = parsedText;
1641
-
1642
- for(i = 0, len = emptyDiv.childNodes.length; i < len; i++){
1643
- fragment.appendChild(emptyDiv.childNodes[i].cloneNode(true));
1644
- }
1645
- }
1646
- return fragment.cloneNode(true);
1647
- };
1648
-
1649
- }
1650
- return fn ? fn.apply(this, arguments) : fragment.cloneNode(true);
1651
- },
1652
- track: null,
1653
-
1654
-
1655
- id: ''
1656
- //todo-->
1657
- // ,
1658
- // snapToLines: true,
1659
- // line: 'auto',
1660
- // size: 100,
1661
- // position: 50,
1662
- // vertical: '',
1663
- // align: 'middle'
1664
- };
1665
-
1666
-
1667
-
1668
-
1669
-
1670
- mediaelement.createCueList = function(){
1671
- return $.extend([], cueListProto);
1672
- };
1673
-
1674
- mediaelement.parseCueTextToHTML = (function(){
1675
- var tagSplits = /(<\/?[^>]+>)/ig;
1676
- var allowedTags = /^(?:c|v|ruby|rt|b|i|u)/;
1677
- var regEnd = /\<\s*\//;
1678
- var addToTemplate = function(localName, attribute, tag, html){
1679
- var ret;
1680
- if(regEnd.test(html)){
1681
- ret = '</'+ localName +'>';
1682
- } else {
1683
- tag.splice(0, 1);
1684
- ret = '<'+ localName +' '+ attribute +'="'+ (tag.join(' ').replace(/\"/g, '&#34;')) +'">';
1685
- }
1686
- return ret;
1687
- };
1688
- var replacer = function(html){
1689
- var tag = html.replace(/[<\/>]+/ig,"").split(/[\s\.]+/);
1690
- if(tag[0]){
1691
- tag[0] = tag[0].toLowerCase();
1692
- if(allowedTags.test(tag[0])){
1693
- if(tag[0] == 'c'){
1694
- html = addToTemplate('span', 'class', tag, html);
1695
- } else if(tag[0] == 'v'){
1696
- html = addToTemplate('q', 'title', tag, html);
1697
- }
1698
- } else {
1699
- html = "";
1700
- }
1701
- }
1702
- return html;
1703
- };
1704
-
1705
- return function(cueText){
1706
- return cueText.replace(tagSplits, replacer);
1707
- };
1708
- })();
1709
-
1710
- mediaelement.loadTextTrack = function(mediaelem, track, trackData, _default){
1711
- var loadEvents = 'play playing timeupdate updatetrackdisplay';
1712
- var obj = trackData.track;
1713
- var load = function(){
1714
- var src = $.prop(track, 'src');
1715
- var error;
1716
- var ajax;
1717
- if(obj.mode != 'disabled' && src && $.attr(track, 'src')){
1718
- $(mediaelem).unbind(loadEvents, load);
1719
- $(track).unbind('checktrackmode', load);
1720
- if(!obj.readyState){
1721
- error = function(){
1722
- obj.readyState = 3;
1723
- obj.cues = null;
1724
- obj.activeCues = obj.shimActiveCues = obj._shimActiveCues = null;
1725
- $(track).triggerHandler('error');
1726
- };
1727
- obj.readyState = 1;
1728
- try {
1729
- obj.cues = mediaelement.createCueList();
1730
- obj.activeCues = obj.shimActiveCues = obj._shimActiveCues = mediaelement.createCueList();
1731
- ajax = $.ajax({
1732
- dataType: 'text',
1733
- url: src,
1734
- success: function(text){
1735
- if(ajax.getResponseHeader('content-type') != 'text/vtt'){
1736
- webshims.error('set the mime-type of your WebVTT files to text/vtt. see: http://dev.w3.org/html5/webvtt/#text/vtt');
1737
- }
1738
- mediaelement.parseCaptions(text, obj, function(cues){
1739
- if(cues && 'length' in cues){
1740
- obj.readyState = 2;
1741
- $(track).triggerHandler('load');
1742
- $(mediaelem).triggerHandler('updatetrackdisplay');
1743
- } else {
1744
- error();
1745
- }
1746
- });
1747
-
1748
- },
1749
- error: error
1750
- });
1751
- } catch(er){
1752
- error();
1753
- webshims.warn(er);
1754
- }
1755
- }
1756
- }
1757
- };
1758
- obj.readyState = 0;
1759
- obj.shimActiveCues = null;
1760
- obj._shimActiveCues = null;
1761
- obj.activeCues = null;
1762
- obj.cues = null;
1763
- $(mediaelem).unbind(loadEvents, load);
1764
- $(track).unbind('checktrackmode', load);
1765
- $(mediaelem).bind(loadEvents, load);
1766
- $(track).bind('checktrackmode', load);
1767
- if(_default){
1768
- obj.mode = showTracks[obj.kind] ? 'showing' : 'hidden';
1769
- load();
1770
- }
1771
- };
1772
-
1773
- mediaelement.createTextTrack = function(mediaelem, track){
1774
- var obj, trackData;
1775
- if(track.nodeName){
1776
- trackData = webshims.data(track, 'trackData');
1777
-
1778
- if(trackData){
1779
- refreshTrack(track, trackData);
1780
- obj = trackData.track;
1781
- }
1782
- }
1783
-
1784
- if(!obj){
1785
- obj = createEventTarget(webshims.objectCreate(textTrackProto));
1786
- copyProps.forEach(function(copyProp){
1787
- var prop = $.prop(track, copyProp);
1788
- if(prop){
1789
- if(copyProp == 'srclang'){
1790
- copyProp = 'language';
1791
- }
1792
- obj[copyProp] = prop;
1793
- }
1794
- });
1795
-
1796
-
1797
- if(track.nodeName){
1798
- trackData = webshims.data(track, 'trackData', {track: obj});
1799
- mediaelement.loadTextTrack(mediaelem, track, trackData, $.prop(track, 'default'));
1800
- } else {
1801
- obj.cues = mediaelement.createCueList();
1802
- obj.activeCues = obj._shimActiveCues = obj.shimActiveCues = mediaelement.createCueList();
1803
- obj.mode = 'hidden';
1804
- obj.readyState = 2;
1805
- }
1806
- }
1807
- return obj;
1808
- };
1809
-
1810
-
1811
- /*
1812
- taken from:
1813
- Captionator 0.5.1 [CaptionCrunch]
1814
- Christopher Giffard, 2011
1815
- Share and enjoy
1816
-
1817
- https://github.com/cgiffard/Captionator
1818
-
1819
- modified for webshims
1820
- */
1821
- mediaelement.parseCaptionChunk = (function(){
1822
- // Set up timestamp parsers
1823
- var WebVTTTimestampParser = /^(\d{2})?:?(\d{2}):(\d{2})\.(\d+)\s+\-\-\>\s+(\d{2})?:?(\d{2}):(\d{2})\.(\d+)\s*(.*)/;
1824
- var GoogleTimestampParser = /^([\d\.]+)\s+\+([\d\.]+)\s*(.*)/;
1825
- var WebVTTDEFAULTSCueParser = /^(DEFAULTS|DEFAULT)\s+\-\-\>\s+(.*)/g;
1826
- var WebVTTSTYLECueParser = /^(STYLE|STYLES)\s+\-\-\>\s*\n([\s\S]*)/g;
1827
- var WebVTTCOMMENTCueParser = /^(COMMENT|COMMENTS)\s+\-\-\>\s+(.*)/g;
1828
-
1829
- return function(subtitleElement,objectCount){
1830
- var cueDefaults = [];
1831
-
1832
- var subtitleParts, timeIn, timeOut, html, timeData, subtitlePartIndex, cueSettings = "", id, specialCueData;
1833
- var timestampMatch, tmpCue;
1834
-
1835
- // WebVTT Special Cue Logic
1836
- if ((specialCueData = WebVTTDEFAULTSCueParser.exec(subtitleElement))) {
1837
- // cueDefaults = specialCueData.slice(2).join("");
1838
- // cueDefaults = cueDefaults.split(/\s+/g).filter(function(def) { return def && !!def.length; });
1839
- return null;
1840
- } else if ((specialCueData = WebVTTSTYLECueParser.exec(subtitleElement))) {
1841
- return null;
1842
- } else if ((specialCueData = WebVTTCOMMENTCueParser.exec(subtitleElement))) {
1843
- return null; // At this stage, we don't want to do anything with these.
1844
- }
1845
-
1846
- subtitleParts = subtitleElement.split(/\n/g);
1847
-
1848
- // Trim off any blank lines (logically, should only be max. one, but loop to be sure)
1849
- while (!subtitleParts[0].replace(/\s+/ig,"").length && subtitleParts.length > 0) {
1850
- subtitleParts.shift();
1851
- }
1852
-
1853
- if (subtitleParts[0].match(/^\s*[a-z0-9]+\s*$/ig)) {
1854
- // The identifier becomes the cue ID (when *we* load the cues from file. Programatically created cues can have an ID of whatever.)
1855
- id = String(subtitleParts.shift().replace(/\s*/ig,""));
1856
- }
1857
-
1858
- for (subtitlePartIndex = 0; subtitlePartIndex < subtitleParts.length; subtitlePartIndex ++) {
1859
- var timestamp = subtitleParts[subtitlePartIndex];
1860
-
1861
- if ((timestampMatch = WebVTTTimestampParser.exec(timestamp))) {
1862
-
1863
- // WebVTT
1864
-
1865
- timeData = timestampMatch.slice(1);
1866
-
1867
- timeIn = parseInt((timeData[0]||0) * 60 * 60,10) + // Hours
1868
- parseInt((timeData[1]||0) * 60,10) + // Minutes
1869
- parseInt((timeData[2]||0),10) + // Seconds
1870
- parseFloat("0." + (timeData[3]||0)); // MS
1871
-
1872
- timeOut = parseInt((timeData[4]||0) * 60 * 60,10) + // Hours
1873
- parseInt((timeData[5]||0) * 60,10) + // Minutes
1874
- parseInt((timeData[6]||0),10) + // Seconds
1875
- parseFloat("0." + (timeData[7]||0)); // MS
1876
- /*
1877
- if (timeData[8]) {
1878
- cueSettings = timeData[8];
1879
- }
1880
- */
1881
- }
1882
-
1883
- // We've got the timestamp - return all the other unmatched lines as the raw subtitle data
1884
- subtitleParts = subtitleParts.slice(0,subtitlePartIndex).concat(subtitleParts.slice(subtitlePartIndex+1));
1885
- break;
1886
- }
1887
-
1888
- if (!timeIn && !timeOut) {
1889
- // We didn't extract any time information. Assume the cue is invalid!
1890
- return null;
1891
- }
1892
- /*
1893
- // Consolidate cue settings, convert defaults to object
1894
- var compositeCueSettings =
1895
- cueDefaults
1896
- .reduce(function(previous,current,index,array){
1897
- previous[current.split(":")[0]] = current.split(":")[1];
1898
- return previous;
1899
- },{});
1900
-
1901
- // Loop through cue settings, replace defaults with cue specific settings if they exist
1902
- compositeCueSettings =
1903
- cueSettings
1904
- .split(/\s+/g)
1905
- .filter(function(set) { return set && !!set.length; })
1906
- // Convert array to a key/val object
1907
- .reduce(function(previous,current,index,array){
1908
- previous[current.split(":")[0]] = current.split(":")[1];
1909
- return previous;
1910
- },compositeCueSettings);
1911
-
1912
- // Turn back into string like the TextTrackCue constructor expects
1913
- cueSettings = "";
1914
- for (var key in compositeCueSettings) {
1915
- if (compositeCueSettings.hasOwnProperty(key)) {
1916
- cueSettings += !!cueSettings.length ? " " : "";
1917
- cueSettings += key + ":" + compositeCueSettings[key];
1918
- }
1919
- }
1920
- */
1921
- // The remaining lines are the subtitle payload itself (after removing an ID if present, and the time);
1922
- html = subtitleParts.join("\n");
1923
- tmpCue = new TextTrackCue(timeIn, timeOut, html);
1924
- if(id){
1925
- tmpCue.id = id;
1926
- }
1927
- return tmpCue;
1928
- };
1929
- })();
1930
-
1931
- mediaelement.parseCaptions = function(captionData, track, complete) {
1932
- var subtitles = mediaelement.createCueList();
1933
- var cue, lazyProcess, regWevVTT;
1934
- var startDate;
1935
- var isWEBVTT;
1936
- if (captionData) {
1937
-
1938
- regWevVTT = /^WEBVTT(\s*FILE)?/ig;
1939
-
1940
- lazyProcess = function(i, len){
1941
-
1942
- for(; i < len; i++){
1943
- cue = captionData[i];
1944
- if(regWevVTT.test(cue)){
1945
- isWEBVTT = true;
1946
- } else if(cue.replace(/\s*/ig,"").length){
1947
- if(!isWEBVTT){
1948
- webshims.error('please use WebVTT format. This is the standard');
1949
- complete(null);
1950
- break;
1951
- }
1952
- cue = mediaelement.parseCaptionChunk(cue, i);
1953
- if(cue){
1954
- track.addCue(cue);
1955
- }
1956
- }
1957
- if(startDate < (new Date().getTime()) - 9){
1958
- i++;
1959
- setTimeout(function(){
1960
- startDate = new Date().getTime();
1961
- lazyProcess(i, len);
1962
- }, 90);
1963
-
1964
- break;
1965
- }
1966
- }
1967
- if(i >= len){
1968
- if(!isWEBVTT){
1969
- webshims.error('please use WebVTT format. This is the standard');
1970
- }
1971
- complete(track.cues);
1972
- }
1973
- };
1974
-
1975
- captionData = captionData.replace(/\r\n/g,"\n");
1976
-
1977
- setTimeout(function(){
1978
- captionData = captionData.replace(/\r/g,"\n");
1979
- setTimeout(function(){
1980
- startDate = new Date().getTime();
1981
- captionData = captionData.split(/\n\n+/g);
1982
- lazyProcess(0, captionData.length);
1983
- }, 9);
1984
- }, 9);
1985
-
1986
- } else {
1987
- webshims.error("Required parameter captionData not supplied.");
1988
- }
1989
- };
1990
-
1991
-
1992
- mediaelement.createTrackList = function(mediaelem, baseData){
1993
- baseData = baseData || webshims.data(mediaelem, 'mediaelementBase') || webshims.data(mediaelem, 'mediaelementBase', {});
1994
- if(!baseData.textTracks){
1995
- baseData.textTracks = [];
1996
- webshims.defineProperties(baseData.textTracks, {
1997
- onaddtrack: {value: null},
1998
- onremovetrack: {value: null}
1999
- });
2000
- createEventTarget(baseData.textTracks);
2001
- }
2002
- return baseData.textTracks;
2003
- };
2004
-
2005
- if(!Modernizr.track){
2006
- webshims.defineNodeNamesBooleanProperty(['track'], 'default');
2007
- webshims.reflectProperties(['track'], ['srclang', 'label']);
2008
-
2009
- webshims.defineNodeNameProperties('track', {
2010
- src: {
2011
- //attr: {},
2012
- reflect: true,
2013
- propType: 'src'
2014
- }
2015
- });
2016
- }
2017
-
2018
- webshims.defineNodeNameProperties('track', {
2019
- kind: {
2020
- attr: Modernizr.track ? {
2021
- set: function(value){
2022
- var trackData = webshims.data(this, 'trackData');
2023
- this.setAttribute('data-kind', value);
2024
- if(trackData){
2025
- trackData.attrKind = value;
2026
- }
2027
- },
2028
- get: function(){
2029
- var trackData = webshims.data(this, 'trackData');
2030
- if(trackData && ('attrKind' in trackData)){
2031
- return trackData.attrKind;
2032
- }
2033
- return this.getAttribute('kind');
2034
- }
2035
- } : {},
2036
- reflect: true,
2037
- propType: 'enumarated',
2038
- defaultValue: 'subtitles',
2039
- limitedTo: ['subtitles', 'captions', 'descriptions', 'chapters', 'metadata']
2040
- }
2041
- });
2042
-
2043
- webshims.onNodeNamesPropertyModify('track', 'kind', function(){
2044
- var trackData = webshims.data(this, 'trackData');
2045
- if(trackData){
2046
- trackData.track.kind = $.prop(this, 'kind');
2047
- refreshTrack(this, trackData);
2048
- }
2049
- });
2050
-
2051
- webshims.onNodeNamesPropertyModify('track', 'src', function(val){
2052
- if(val){
2053
- var data = webshims.data(this, 'trackData');
2054
- var media;
2055
- if(data){
2056
- media = $(this).closest('video, audio');
2057
- if(media[0]){
2058
- mediaelement.loadTextTrack(media, this, data);
2059
- }
2060
- }
2061
- }
2062
-
2063
- });
2064
-
2065
- //
2066
-
2067
- webshims.defineNodeNamesProperties(['track'], {
2068
- ERROR: {
2069
- value: 3
2070
- },
2071
- LOADED: {
2072
- value: 2
2073
- },
2074
- LOADING: {
2075
- value: 1
2076
- },
2077
- NONE: {
2078
- value: 0
2079
- },
2080
- readyState: {
2081
- get: function(){
2082
- return ($.prop(this, 'track') || {readyState: 0}).readyState;
2083
- },
2084
- writeable: false
2085
- },
2086
- track: {
2087
- get: function(){
2088
- return mediaelement.createTextTrack($(this).closest('audio, video')[0], this);
2089
- },
2090
- writeable: false
2091
- }
2092
- }, 'prop');
2093
-
2094
- webshims.defineNodeNamesProperties(['audio', 'video'], {
2095
- textTracks: {
2096
- get: function(){
2097
-
2098
- var media = this;
2099
- var baseData = webshims.data(media, 'mediaelementBase') || webshims.data(media, 'mediaelementBase', {});
2100
- var tracks = mediaelement.createTrackList(media, baseData);
2101
- if(!baseData.blockTrackListUpdate){
2102
- updateMediaTrackList.call(media, baseData, tracks);
2103
- }
2104
- return tracks;
2105
- },
2106
- writeable: false
2107
- },
2108
- addTextTrack: {
2109
- value: function(kind, label, lang){
2110
- var textTrack = mediaelement.createTextTrack(this, {
2111
- kind: kind || '',
2112
- label: label || '',
2113
- srclang: lang || ''
2114
- });
2115
- var baseData = webshims.data(this, 'mediaelementBase') || webshims.data(this, 'mediaelementBase', {});
2116
- if (!baseData.scriptedTextTracks) {
2117
- baseData.scriptedTextTracks = [];
2118
- }
2119
- baseData.scriptedTextTracks.push(textTrack);
2120
- updateMediaTrackList.call(this);
2121
- return textTrack;
2122
- }
2123
- }
2124
- }, 'prop');
2125
-
2126
-
2127
- $(document).bind('emptied ended updatetracklist', function(e){
2128
- if($(e.target).is('audio, video')){
2129
- var baseData = webshims.data(e.target, 'mediaelementBase');
2130
- if(baseData){
2131
- clearTimeout(baseData.updateTrackListTimer);
2132
- baseData.updateTrackListTimer = setTimeout(function(){
2133
- updateMediaTrackList.call(e.target, baseData);
2134
- }, 0);
2135
- }
2136
- }
2137
- });
2138
-
2139
- var getNativeReadyState = function(trackElem, textTrack){
2140
- return textTrack.readyState || trackElem.readyState;
2141
- };
2142
-
2143
- webshims.addReady(function(context, insertedElement){
2144
- var insertedMedia = insertedElement.filter('video, audio, track').closest('audio, video');
2145
- $('video, audio', context)
2146
- .add(insertedMedia)
2147
- .each(function(){
2148
- updateMediaTrackList.call(this);
2149
- })
2150
- .each(function(){
2151
- if(Modernizr.track){
2152
- var shimedTextTracks = $.prop(this, 'textTracks');
2153
- var origTextTracks = this.textTracks;
2154
- if(shimedTextTracks.length != origTextTracks.length){
2155
- webshims.error("textTracks couldn't be copied");
2156
- }
2157
-
2158
- $('track', this)
2159
- .each(function(){
2160
- var shimedTrack = $.prop(this, 'track');
2161
- var origTrack = this.track;
2162
- var kind;
2163
- var readyState;
2164
- if(origTrack){
2165
- kind = $.prop(this, 'kind');
2166
- readyState = getNativeReadyState(this, origTrack);
2167
- if (origTrack.mode || readyState) {
2168
- shimedTrack.mode = origTrack.mode;
2169
- }
2170
- //disable track from showing + remove UI
2171
- if(kind != 'descriptions'){
2172
- origTrack.mode = (typeof origTrack.mode == 'string') ? 'disabled' : 0;
2173
- this.kind = 'metadata';
2174
- $(this).attr({kind: kind});
2175
- }
2176
-
2177
- }
2178
- })
2179
- .bind('load error', function(e){
2180
- if(e.originalEvent){
2181
- e.stopImmediatePropagation();
2182
- }
2183
- })
2184
- ;
2185
- }
2186
- })
2187
- ;
2188
- insertedMedia.each(function(){
2189
- var media = this;
2190
- var baseData = webshims.data(media, 'mediaelementBase');
2191
- if(baseData){
2192
- clearTimeout(baseData.updateTrackListTimer);
2193
- baseData.updateTrackListTimer = setTimeout(function(){
2194
- updateMediaTrackList.call(media, baseData);
2195
- }, 9);
2196
- }
2197
- });
2198
- });
2199
-
2200
- if(Modernizr.track){
2201
- $('video, audio').trigger('trackapichange');
2202
- }
2203
-
1446
+ })(jQuery, Modernizr, jQuery.webshims);jQuery.webshims.register('track', function($, webshims, window, document, undefined){
1447
+ var mediaelement = webshims.mediaelement;
1448
+ var id = new Date().getTime();
1449
+ //descriptions are not really shown, but they are inserted into the dom
1450
+ var showTracks = {subtitles: 1, captions: 1, descriptions: 1};
1451
+ var notImplemented = function(){
1452
+ webshims.error('not implemented yet');
1453
+ };
1454
+ var supportTrackMod = Modernizr.ES5 && Modernizr.objectAccessor;
1455
+ var createEventTarget = function(obj){
1456
+ var eventList = {};
1457
+ obj.addEventListener = function(name, fn){
1458
+ if(eventList[name]){
1459
+ webshims.error('always use $.bind to the shimed event: '+ name +' already bound fn was: '+ eventList[name] +' your fn was: '+ fn);
1460
+ }
1461
+ eventList[name] = fn;
1462
+
1463
+ };
1464
+ obj.removeEventListener = function(name, fn){
1465
+ if(eventList[name] && eventList[name] != fn){
1466
+ webshims.error('always use $.bind/$.unbind to the shimed event: '+ name +' already bound fn was: '+ eventList[name] +' your fn was: '+ fn);
1467
+ }
1468
+ if(eventList[name]){
1469
+ delete eventList[name];
1470
+ }
1471
+ };
1472
+ return obj;
1473
+ };
1474
+
1475
+
1476
+ var cueListProto = {
1477
+ getCueById: function(id){
1478
+ var cue = null;
1479
+ for(var i = 0, len = this.length; i < len; i++){
1480
+ if(this[i].id === id){
1481
+ cue = this[i];
1482
+ break;
1483
+ }
1484
+ }
1485
+ return cue;
1486
+ }
1487
+ };
1488
+
1489
+ var textTrackProto = {
1490
+ shimActiveCues: null,
1491
+ _shimActiveCues: null,
1492
+ activeCues: null,
1493
+ cues: null,
1494
+ kind: 'subtitles',
1495
+ label: '',
1496
+ language: '',
1497
+ mode: 'disabled',
1498
+ readyState: 0,
1499
+ oncuechange: null,
1500
+ toString: function() {
1501
+ return "[object TextTrack]";
1502
+ },
1503
+ addCue: function(cue){
1504
+ if(!this.cues){
1505
+ this.cues = mediaelement.createCueList();
1506
+ } else {
1507
+ var lastCue = this.cues[this.cues.length-1];
1508
+ if(lastCue && lastCue.startTime > cue.startTime){
1509
+ webshims.error("cue startTime higher than previous cue's startTime");
1510
+ }
1511
+ }
1512
+ if(cue.track && cue.track.removeCue){
1513
+ cue.track.removeCue(cue);
1514
+ }
1515
+ cue.track = this;
1516
+ this.cues.push(cue);
1517
+ },
1518
+ //ToDo: make it more dynamic
1519
+ removeCue: function(cue){
1520
+ var cues = this.cues || [];
1521
+ var i = 0;
1522
+ var len = cues.length;
1523
+ if(cue.track != this){
1524
+ webshims.error("cue not part of track");
1525
+ return;
1526
+ }
1527
+ for(; i < len; i++){
1528
+ if(cues[i] === cue){
1529
+ cues.splice(i, 1);
1530
+ cue.track = null;
1531
+ break;
1532
+ }
1533
+ }
1534
+ if(cue.track){
1535
+ webshims.error("cue not part of track");
1536
+ return;
1537
+ }
1538
+ },
1539
+ DISABLED: 'disabled',
1540
+ OFF: 'disabled',
1541
+ HIDDEN: 'hidden',
1542
+ SHOWING: 'showing',
1543
+ ERROR: 3,
1544
+ LOADED: 2,
1545
+ LOADING: 1,
1546
+ NONE: 0
1547
+ };
1548
+ var copyProps = ['kind', 'label', 'srclang'];
1549
+ var copyName = {srclang: 'language'};
1550
+
1551
+ var owns = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
1552
+
1553
+ var updateMediaTrackList = function(baseData, trackList){
1554
+ var removed = [];
1555
+ var added = [];
1556
+ var newTracks = [];
1557
+ var i, len;
1558
+ if(!baseData){
1559
+ baseData = webshims.data(this, 'mediaelementBase') || webshims.data(this, 'mediaelementBase', {});
1560
+ }
1561
+
1562
+ if(!trackList){
1563
+ baseData.blockTrackListUpdate = true;
1564
+ trackList = $.prop(this, 'textTracks');
1565
+ baseData.blockTrackListUpdate = false;
1566
+ }
1567
+
1568
+ clearTimeout(baseData.updateTrackListTimer);
1569
+
1570
+ $('track', this).each(function(){
1571
+ var track = $.prop(this, 'track');
1572
+ newTracks.push(track);
1573
+ if(trackList.indexOf(track) == -1){
1574
+ added.push(track);
1575
+ }
1576
+ });
1577
+
1578
+ if(baseData.scriptedTextTracks){
1579
+ for(i = 0, len = baseData.scriptedTextTracks.length; i < len; i++){
1580
+ newTracks.push(baseData.scriptedTextTracks[i]);
1581
+ if(trackList.indexOf(baseData.scriptedTextTracks[i]) == -1){
1582
+ added.push(baseData.scriptedTextTracks[i]);
1583
+ }
1584
+ }
1585
+ }
1586
+
1587
+ for(i = 0, len = trackList.length; i < len; i++){
1588
+ if(newTracks.indexOf(trackList[i]) == -1){
1589
+ removed.push(trackList[i]);
1590
+ }
1591
+ }
1592
+
1593
+ if(removed.length || added.length){
1594
+ trackList.splice(0);
1595
+
1596
+ for(i = 0, len = newTracks.length; i < len; i++){
1597
+ trackList.push(newTracks[i]);
1598
+ }
1599
+ for(i = 0, len = removed.length; i < len; i++){
1600
+ $([trackList]).triggerHandler($.Event({type: 'removetrack', track: trackList, track: removed[i]}));
1601
+ }
1602
+ for(i = 0, len = added.length; i < len; i++){
1603
+ $([trackList]).triggerHandler($.Event({type: 'addtrack', track: trackList, track: added[i]}));
1604
+ }
1605
+ if(baseData.scriptedTextTracks || removed.length){
1606
+ $(this).triggerHandler('updatetrackdisplay');
1607
+ }
1608
+ }
1609
+ };
1610
+
1611
+ var refreshTrack = function(track, trackData){
1612
+ if(!trackData){
1613
+ trackData = webshims.data(track, 'trackData');
1614
+ }
1615
+ if(trackData && !trackData.isTriggering){
1616
+ trackData.isTriggering = true;
1617
+ setTimeout(function(){
1618
+ if(!(trackData.track || {}).readyState){
1619
+ $(track).triggerHandler('checktrackmode');
1620
+ } else {
1621
+ $(track).closest('audio, video').triggerHandler('updatetrackdisplay');
1622
+ }
1623
+ trackData.isTriggering = false;
1624
+ }, 1);
1625
+ }
1626
+ };
1627
+
1628
+ var emptyDiv = $('<div />')[0];
1629
+ window.TextTrackCue = function(startTime, endTime, text){
1630
+ if(arguments.length != 3){
1631
+ webshims.error("wrong arguments.length for TextTrackCue.constructor");
1632
+ }
1633
+
1634
+ this.startTime = startTime;
1635
+ this.endTime = endTime;
1636
+ this.text = text;
1637
+
1638
+ this.id = "";
1639
+ this.pauseOnExit = false;
1640
+
1641
+ createEventTarget(this);
1642
+ };
1643
+
1644
+ window.TextTrackCue.prototype = {
1645
+
1646
+ onenter: null,
1647
+ onexit: null,
1648
+ pauseOnExit: false,
1649
+ getCueAsHTML: function(){
1650
+ var lastText = "";
1651
+ var parsedText = "";
1652
+ var fragment = document.createDocumentFragment();
1653
+ var fn;
1654
+ if(!owns(this, 'getCueAsHTML')){
1655
+ fn = this.getCueAsHTML = function(){
1656
+ var i, len;
1657
+ if(lastText != this.text){
1658
+ lastText = this.text;
1659
+ parsedText = mediaelement.parseCueTextToHTML(lastText);
1660
+ emptyDiv.innerHTML = parsedText;
1661
+
1662
+ for(i = 0, len = emptyDiv.childNodes.length; i < len; i++){
1663
+ fragment.appendChild(emptyDiv.childNodes[i].cloneNode(true));
1664
+ }
1665
+ }
1666
+ return fragment.cloneNode(true);
1667
+ };
1668
+
1669
+ }
1670
+ return fn ? fn.apply(this, arguments) : fragment.cloneNode(true);
1671
+ },
1672
+ track: null,
1673
+
1674
+
1675
+ id: ''
1676
+ //todo-->
1677
+ // ,
1678
+ // snapToLines: true,
1679
+ // line: 'auto',
1680
+ // size: 100,
1681
+ // position: 50,
1682
+ // vertical: '',
1683
+ // align: 'middle'
1684
+ };
1685
+
1686
+
1687
+
1688
+
1689
+
1690
+ mediaelement.createCueList = function(){
1691
+ return $.extend([], cueListProto);
1692
+ };
1693
+
1694
+ mediaelement.parseCueTextToHTML = (function(){
1695
+ var tagSplits = /(<\/?[^>]+>)/ig;
1696
+ var allowedTags = /^(?:c|v|ruby|rt|b|i|u)/;
1697
+ var regEnd = /\<\s*\//;
1698
+ var addToTemplate = function(localName, attribute, tag, html){
1699
+ var ret;
1700
+ if(regEnd.test(html)){
1701
+ ret = '</'+ localName +'>';
1702
+ } else {
1703
+ tag.splice(0, 1);
1704
+ ret = '<'+ localName +' '+ attribute +'="'+ (tag.join(' ').replace(/\"/g, '&#34;')) +'">';
1705
+ }
1706
+ return ret;
1707
+ };
1708
+ var replacer = function(html){
1709
+ var tag = html.replace(/[<\/>]+/ig,"").split(/[\s\.]+/);
1710
+ if(tag[0]){
1711
+ tag[0] = tag[0].toLowerCase();
1712
+ if(allowedTags.test(tag[0])){
1713
+ if(tag[0] == 'c'){
1714
+ html = addToTemplate('span', 'class', tag, html);
1715
+ } else if(tag[0] == 'v'){
1716
+ html = addToTemplate('q', 'title', tag, html);
1717
+ }
1718
+ } else {
1719
+ html = "";
1720
+ }
1721
+ }
1722
+ return html;
1723
+ };
1724
+
1725
+ return function(cueText){
1726
+ return cueText.replace(tagSplits, replacer);
1727
+ };
1728
+ })();
1729
+
1730
+ mediaelement.loadTextTrack = function(mediaelem, track, trackData, _default){
1731
+ var loadEvents = 'play playing timeupdate updatetrackdisplay';
1732
+ var obj = trackData.track;
1733
+ var load = function(){
1734
+ var src = $.prop(track, 'src');
1735
+ var error;
1736
+ var ajax;
1737
+ if(obj.mode != 'disabled' && src && $.attr(track, 'src')){
1738
+ $(mediaelem).unbind(loadEvents, load);
1739
+ $(track).unbind('checktrackmode', load);
1740
+ if(!obj.readyState){
1741
+ error = function(){
1742
+ obj.readyState = 3;
1743
+ obj.cues = null;
1744
+ obj.activeCues = obj.shimActiveCues = obj._shimActiveCues = null;
1745
+ $(track).triggerHandler('error');
1746
+ };
1747
+ obj.readyState = 1;
1748
+ try {
1749
+ obj.cues = mediaelement.createCueList();
1750
+ obj.activeCues = obj.shimActiveCues = obj._shimActiveCues = mediaelement.createCueList();
1751
+ ajax = $.ajax({
1752
+ dataType: 'text',
1753
+ url: src,
1754
+ success: function(text){
1755
+ if(ajax.getResponseHeader('content-type') != 'text/vtt'){
1756
+ webshims.error('set the mime-type of your WebVTT files to text/vtt. see: http://dev.w3.org/html5/webvtt/#text/vtt');
1757
+ }
1758
+ mediaelement.parseCaptions(text, obj, function(cues){
1759
+ if(cues && 'length' in cues){
1760
+ obj.readyState = 2;
1761
+ $(track).triggerHandler('load');
1762
+ $(mediaelem).triggerHandler('updatetrackdisplay');
1763
+ } else {
1764
+ error();
1765
+ }
1766
+ });
1767
+
1768
+ },
1769
+ error: error
1770
+ });
1771
+ } catch(er){
1772
+ error();
1773
+ webshims.warn(er);
1774
+ }
1775
+ }
1776
+ }
1777
+ };
1778
+ obj.readyState = 0;
1779
+ obj.shimActiveCues = null;
1780
+ obj._shimActiveCues = null;
1781
+ obj.activeCues = null;
1782
+ obj.cues = null;
1783
+ $(mediaelem).unbind(loadEvents, load);
1784
+ $(track).unbind('checktrackmode', load);
1785
+ $(mediaelem).bind(loadEvents, load);
1786
+ $(track).bind('checktrackmode', load);
1787
+ if(_default){
1788
+ obj.mode = showTracks[obj.kind] ? 'showing' : 'hidden';
1789
+ load();
1790
+ }
1791
+ };
1792
+
1793
+ mediaelement.createTextTrack = function(mediaelem, track){
1794
+ var obj, trackData;
1795
+ if(track.nodeName){
1796
+ trackData = webshims.data(track, 'trackData');
1797
+
1798
+ if(trackData){
1799
+ refreshTrack(track, trackData);
1800
+ obj = trackData.track;
1801
+ }
1802
+ }
1803
+
1804
+ if(!obj){
1805
+ obj = createEventTarget(webshims.objectCreate(textTrackProto));
1806
+
1807
+ if(!supportTrackMod){
1808
+ copyProps.forEach(function(copyProp){
1809
+ var prop = $.prop(track, copyProp);
1810
+ if(prop){
1811
+ obj[copyName[copyProp] || copyProp] = prop;
1812
+ }
1813
+ });
1814
+ }
1815
+
1816
+
1817
+ if(track.nodeName){
1818
+
1819
+ if(supportTrackMod){
1820
+ copyProps.forEach(function(copyProp){
1821
+ webshims.defineProperty(obj, copyName[copyProp] || copyProp, {
1822
+ get: function(){
1823
+ return $.prop(track, copyProp);
1824
+ }
1825
+ });
1826
+ });
1827
+ }
1828
+
1829
+ trackData = webshims.data(track, 'trackData', {track: obj});
1830
+ mediaelement.loadTextTrack(mediaelem, track, trackData, ($.prop(track, 'default') && $(track).siblings('track[default]').andSelf()[0] == track));
1831
+ } else {
1832
+ if(supportTrackMod){
1833
+ copyProps.forEach(function(copyProp){
1834
+ webshims.defineProperty(obj, copyName[copyProp] || copyProp, {
1835
+ value: track[copyProp],
1836
+ writeable: false
1837
+ });
1838
+ });
1839
+ }
1840
+ obj.cues = mediaelement.createCueList();
1841
+ obj.activeCues = obj._shimActiveCues = obj.shimActiveCues = mediaelement.createCueList();
1842
+ obj.mode = 'hidden';
1843
+ obj.readyState = 2;
1844
+ }
1845
+ }
1846
+ return obj;
1847
+ };
1848
+
1849
+
1850
+ /*
1851
+ taken from:
1852
+ Captionator 0.5.1 [CaptionCrunch]
1853
+ Christopher Giffard, 2011
1854
+ Share and enjoy
1855
+
1856
+ https://github.com/cgiffard/Captionator
1857
+
1858
+ modified for webshims
1859
+ */
1860
+ mediaelement.parseCaptionChunk = (function(){
1861
+ // Set up timestamp parsers
1862
+ var WebVTTTimestampParser = /^(\d{2})?:?(\d{2}):(\d{2})\.(\d+)\s+\-\-\>\s+(\d{2})?:?(\d{2}):(\d{2})\.(\d+)\s*(.*)/;
1863
+ var GoogleTimestampParser = /^([\d\.]+)\s+\+([\d\.]+)\s*(.*)/;
1864
+ var WebVTTDEFAULTSCueParser = /^(DEFAULTS|DEFAULT)\s+\-\-\>\s+(.*)/g;
1865
+ var WebVTTSTYLECueParser = /^(STYLE|STYLES)\s+\-\-\>\s*\n([\s\S]*)/g;
1866
+ var WebVTTCOMMENTCueParser = /^(COMMENT|COMMENTS)\s+\-\-\>\s+(.*)/g;
1867
+
1868
+ return function(subtitleElement,objectCount){
1869
+ var cueDefaults = [];
1870
+
1871
+ var subtitleParts, timeIn, timeOut, html, timeData, subtitlePartIndex, cueSettings = "", id, specialCueData;
1872
+ var timestampMatch, tmpCue;
1873
+
1874
+ // WebVTT Special Cue Logic
1875
+ if ((specialCueData = WebVTTDEFAULTSCueParser.exec(subtitleElement))) {
1876
+ // cueDefaults = specialCueData.slice(2).join("");
1877
+ // cueDefaults = cueDefaults.split(/\s+/g).filter(function(def) { return def && !!def.length; });
1878
+ return null;
1879
+ } else if ((specialCueData = WebVTTSTYLECueParser.exec(subtitleElement))) {
1880
+ return null;
1881
+ } else if ((specialCueData = WebVTTCOMMENTCueParser.exec(subtitleElement))) {
1882
+ return null; // At this stage, we don't want to do anything with these.
1883
+ }
1884
+
1885
+ subtitleParts = subtitleElement.split(/\n/g);
1886
+
1887
+ // Trim off any blank lines (logically, should only be max. one, but loop to be sure)
1888
+ while (!subtitleParts[0].replace(/\s+/ig,"").length && subtitleParts.length > 0) {
1889
+ subtitleParts.shift();
1890
+ }
1891
+
1892
+ if (subtitleParts[0].match(/^\s*[a-z0-9-\_]+\s*$/ig)) {
1893
+ // The identifier becomes the cue ID (when *we* load the cues from file. Programatically created cues can have an ID of whatever.)
1894
+ id = String(subtitleParts.shift().replace(/\s*/ig,""));
1895
+ }
1896
+
1897
+ for (subtitlePartIndex = 0; subtitlePartIndex < subtitleParts.length; subtitlePartIndex ++) {
1898
+ var timestamp = subtitleParts[subtitlePartIndex];
1899
+
1900
+ if ((timestampMatch = WebVTTTimestampParser.exec(timestamp))) {
1901
+
1902
+ // WebVTT
1903
+
1904
+ timeData = timestampMatch.slice(1);
1905
+
1906
+ timeIn = parseInt((timeData[0]||0) * 60 * 60,10) + // Hours
1907
+ parseInt((timeData[1]||0) * 60,10) + // Minutes
1908
+ parseInt((timeData[2]||0),10) + // Seconds
1909
+ parseFloat("0." + (timeData[3]||0)); // MS
1910
+
1911
+ timeOut = parseInt((timeData[4]||0) * 60 * 60,10) + // Hours
1912
+ parseInt((timeData[5]||0) * 60,10) + // Minutes
1913
+ parseInt((timeData[6]||0),10) + // Seconds
1914
+ parseFloat("0." + (timeData[7]||0)); // MS
1915
+ /*
1916
+ if (timeData[8]) {
1917
+ cueSettings = timeData[8];
1918
+ }
1919
+ */
1920
+ }
1921
+
1922
+ // We've got the timestamp - return all the other unmatched lines as the raw subtitle data
1923
+ subtitleParts = subtitleParts.slice(0,subtitlePartIndex).concat(subtitleParts.slice(subtitlePartIndex+1));
1924
+ break;
1925
+ }
1926
+
1927
+ if (!timeIn && !timeOut) {
1928
+ // We didn't extract any time information. Assume the cue is invalid!
1929
+ webshims.warn("couldn't extract time information: "+[timeIn, timeOut, subtitleParts.join("\n"), id].join(' ; '));
1930
+ return null;
1931
+ }
1932
+ /*
1933
+ // Consolidate cue settings, convert defaults to object
1934
+ var compositeCueSettings =
1935
+ cueDefaults
1936
+ .reduce(function(previous,current,index,array){
1937
+ previous[current.split(":")[0]] = current.split(":")[1];
1938
+ return previous;
1939
+ },{});
1940
+
1941
+ // Loop through cue settings, replace defaults with cue specific settings if they exist
1942
+ compositeCueSettings =
1943
+ cueSettings
1944
+ .split(/\s+/g)
1945
+ .filter(function(set) { return set && !!set.length; })
1946
+ // Convert array to a key/val object
1947
+ .reduce(function(previous,current,index,array){
1948
+ previous[current.split(":")[0]] = current.split(":")[1];
1949
+ return previous;
1950
+ },compositeCueSettings);
1951
+
1952
+ // Turn back into string like the TextTrackCue constructor expects
1953
+ cueSettings = "";
1954
+ for (var key in compositeCueSettings) {
1955
+ if (compositeCueSettings.hasOwnProperty(key)) {
1956
+ cueSettings += !!cueSettings.length ? " " : "";
1957
+ cueSettings += key + ":" + compositeCueSettings[key];
1958
+ }
1959
+ }
1960
+ */
1961
+ // The remaining lines are the subtitle payload itself (after removing an ID if present, and the time);
1962
+ html = subtitleParts.join("\n");
1963
+ tmpCue = new TextTrackCue(timeIn, timeOut, html);
1964
+ if(id){
1965
+ tmpCue.id = id;
1966
+ }
1967
+ return tmpCue;
1968
+ };
1969
+ })();
1970
+
1971
+ mediaelement.parseCaptions = function(captionData, track, complete) {
1972
+ var subtitles = mediaelement.createCueList();
1973
+ var cue, lazyProcess, regWevVTT;
1974
+ var startDate;
1975
+ var isWEBVTT;
1976
+ if (captionData) {
1977
+
1978
+ regWevVTT = /^WEBVTT(\s*FILE)?/ig;
1979
+
1980
+ lazyProcess = function(i, len){
1981
+
1982
+ for(; i < len; i++){
1983
+ cue = captionData[i];
1984
+ if(regWevVTT.test(cue)){
1985
+ isWEBVTT = true;
1986
+ } else if(cue.replace(/\s*/ig,"").length){
1987
+ if(!isWEBVTT){
1988
+ webshims.error('please use WebVTT format. This is the standard');
1989
+ complete(null);
1990
+ break;
1991
+ }
1992
+ cue = mediaelement.parseCaptionChunk(cue, i);
1993
+ if(cue){
1994
+ track.addCue(cue);
1995
+ }
1996
+ }
1997
+ if(startDate < (new Date().getTime()) - 30){
1998
+ i++;
1999
+ setTimeout(function(){
2000
+ startDate = new Date().getTime();
2001
+ lazyProcess(i, len);
2002
+ }, 90);
2003
+
2004
+ break;
2005
+ }
2006
+ }
2007
+ if(i >= len){
2008
+ if(!isWEBVTT){
2009
+ webshims.error('please use WebVTT format. This is the standard');
2010
+ }
2011
+ complete(track.cues);
2012
+ }
2013
+ };
2014
+
2015
+ captionData = captionData.replace(/\r\n/g,"\n");
2016
+
2017
+ setTimeout(function(){
2018
+ captionData = captionData.replace(/\r/g,"\n");
2019
+ setTimeout(function(){
2020
+ startDate = new Date().getTime();
2021
+ captionData = captionData.split(/\n\n+/g);
2022
+ lazyProcess(0, captionData.length);
2023
+ }, 9);
2024
+ }, 9);
2025
+
2026
+ } else {
2027
+ webshims.error("Required parameter captionData not supplied.");
2028
+ }
2029
+ };
2030
+
2031
+
2032
+ mediaelement.createTrackList = function(mediaelem, baseData){
2033
+ baseData = baseData || webshims.data(mediaelem, 'mediaelementBase') || webshims.data(mediaelem, 'mediaelementBase', {});
2034
+ if(!baseData.textTracks){
2035
+ baseData.textTracks = [];
2036
+ webshims.defineProperties(baseData.textTracks, {
2037
+ onaddtrack: {value: null},
2038
+ onremovetrack: {value: null}
2039
+ });
2040
+ createEventTarget(baseData.textTracks);
2041
+ }
2042
+ return baseData.textTracks;
2043
+ };
2044
+
2045
+ if(!Modernizr.track){
2046
+ webshims.defineNodeNamesBooleanProperty(['track'], 'default');
2047
+ webshims.reflectProperties(['track'], ['srclang', 'label']);
2048
+
2049
+ webshims.defineNodeNameProperties('track', {
2050
+ src: {
2051
+ //attr: {},
2052
+ reflect: true,
2053
+ propType: 'src'
2054
+ }
2055
+ });
2056
+ }
2057
+
2058
+ webshims.defineNodeNameProperties('track', {
2059
+ kind: {
2060
+ attr: Modernizr.track ? {
2061
+ set: function(value){
2062
+ var trackData = webshims.data(this, 'trackData');
2063
+ this.setAttribute('data-kind', value);
2064
+ if(trackData){
2065
+ trackData.attrKind = value;
2066
+ }
2067
+ },
2068
+ get: function(){
2069
+ var trackData = webshims.data(this, 'trackData');
2070
+ if(trackData && ('attrKind' in trackData)){
2071
+ return trackData.attrKind;
2072
+ }
2073
+ return this.getAttribute('kind');
2074
+ }
2075
+ } : {},
2076
+ reflect: true,
2077
+ propType: 'enumarated',
2078
+ defaultValue: 'subtitles',
2079
+ limitedTo: ['subtitles', 'captions', 'descriptions', 'chapters', 'metadata']
2080
+ }
2081
+ });
2082
+
2083
+ $.each(copyProps, function(i, copyProp){
2084
+ var name = copyName[copyProp] || copyProp;
2085
+ webshims.onNodeNamesPropertyModify('track', copyProp, function(){
2086
+ var trackData = webshims.data(this, 'trackData');
2087
+ var track = this;
2088
+ if(trackData){
2089
+ if(copyProp == 'kind'){
2090
+ refreshTrack(this, trackData);
2091
+ }
2092
+ if(!supportTrackMod){
2093
+ trackData.track[name] = $.prop(this, copyProp);
2094
+ }
2095
+ clearTimeout(trackData.changedTrackPropTimer);
2096
+ trackData.changedTrackPropTimer = setTimeout(function(){
2097
+ $(track).trigger('updatesubtitlestate');
2098
+ }, 1);
2099
+ }
2100
+ });
2101
+ });
2102
+
2103
+
2104
+ webshims.onNodeNamesPropertyModify('track', 'src', function(val){
2105
+ if(val){
2106
+ var data = webshims.data(this, 'trackData');
2107
+ var media;
2108
+ if(data){
2109
+ media = $(this).closest('video, audio');
2110
+ if(media[0]){
2111
+ mediaelement.loadTextTrack(media, this, data);
2112
+ }
2113
+ }
2114
+ }
2115
+
2116
+ });
2117
+
2118
+ //
2119
+
2120
+ webshims.defineNodeNamesProperties(['track'], {
2121
+ ERROR: {
2122
+ value: 3
2123
+ },
2124
+ LOADED: {
2125
+ value: 2
2126
+ },
2127
+ LOADING: {
2128
+ value: 1
2129
+ },
2130
+ NONE: {
2131
+ value: 0
2132
+ },
2133
+ readyState: {
2134
+ get: function(){
2135
+ return ($.prop(this, 'track') || {readyState: 0}).readyState;
2136
+ },
2137
+ writeable: false
2138
+ },
2139
+ track: {
2140
+ get: function(){
2141
+ return mediaelement.createTextTrack($(this).closest('audio, video')[0], this);
2142
+ },
2143
+ writeable: false
2144
+ }
2145
+ }, 'prop');
2146
+
2147
+ webshims.defineNodeNamesProperties(['audio', 'video'], {
2148
+ textTracks: {
2149
+ get: function(){
2150
+ var media = this;
2151
+ var baseData = webshims.data(media, 'mediaelementBase') || webshims.data(media, 'mediaelementBase', {});
2152
+ var tracks = mediaelement.createTrackList(media, baseData);
2153
+ if(!baseData.blockTrackListUpdate){
2154
+ updateMediaTrackList.call(media, baseData, tracks);
2155
+ }
2156
+ return tracks;
2157
+ },
2158
+ writeable: false
2159
+ },
2160
+ addTextTrack: {
2161
+ value: function(kind, label, lang){
2162
+ var textTrack = mediaelement.createTextTrack(this, {
2163
+ kind: kind || '',
2164
+ label: label || '',
2165
+ srclang: lang || ''
2166
+ });
2167
+ var baseData = webshims.data(this, 'mediaelementBase') || webshims.data(this, 'mediaelementBase', {});
2168
+ if (!baseData.scriptedTextTracks) {
2169
+ baseData.scriptedTextTracks = [];
2170
+ }
2171
+ baseData.scriptedTextTracks.push(textTrack);
2172
+ updateMediaTrackList.call(this);
2173
+ return textTrack;
2174
+ }
2175
+ }
2176
+ }, 'prop');
2177
+
2178
+
2179
+ $(document).bind('emptied ended updatetracklist', function(e){
2180
+ if($(e.target).is('audio, video')){
2181
+ var baseData = webshims.data(e.target, 'mediaelementBase');
2182
+ if(baseData){
2183
+ clearTimeout(baseData.updateTrackListTimer);
2184
+ baseData.updateTrackListTimer = setTimeout(function(){
2185
+ updateMediaTrackList.call(e.target, baseData);
2186
+ }, 0);
2187
+ }
2188
+ }
2189
+ });
2190
+
2191
+ var getNativeReadyState = function(trackElem, textTrack){
2192
+ return textTrack.readyState || trackElem.readyState;
2193
+ };
2194
+
2195
+ webshims.addReady(function(context, insertedElement){
2196
+ var insertedMedia = insertedElement.filter('video, audio, track').closest('audio, video');
2197
+ $('video, audio', context)
2198
+ .add(insertedMedia)
2199
+ .each(function(){
2200
+ updateMediaTrackList.call(this);
2201
+ })
2202
+ .each(function(){
2203
+ if(Modernizr.track){
2204
+ var shimedTextTracks = $.prop(this, 'textTracks');
2205
+ var origTextTracks = this.textTracks;
2206
+ if(shimedTextTracks.length != origTextTracks.length){
2207
+ webshims.error("textTracks couldn't be copied");
2208
+ }
2209
+
2210
+ $('track', this)
2211
+ .each(function(){
2212
+ var shimedTrack = $.prop(this, 'track');
2213
+ var origTrack = this.track;
2214
+ var kind;
2215
+ var readyState;
2216
+ if(origTrack){
2217
+ kind = $.prop(this, 'kind');
2218
+ readyState = getNativeReadyState(this, origTrack);
2219
+ if (origTrack.mode || readyState) {
2220
+ shimedTrack.mode = origTrack.mode;
2221
+ }
2222
+ //disable track from showing + remove UI
2223
+ if(kind != 'descriptions'){
2224
+ origTrack.mode = (typeof origTrack.mode == 'string') ? 'disabled' : 0;
2225
+ this.kind = 'metadata';
2226
+ $(this).attr({kind: kind});
2227
+ }
2228
+
2229
+ }
2230
+ })
2231
+ .bind('load error', function(e){
2232
+ if(e.originalEvent){
2233
+ e.stopImmediatePropagation();
2234
+ }
2235
+ })
2236
+ ;
2237
+ }
2238
+ })
2239
+ ;
2240
+ insertedMedia.each(function(){
2241
+ var media = this;
2242
+ var baseData = webshims.data(media, 'mediaelementBase');
2243
+ if(baseData){
2244
+ clearTimeout(baseData.updateTrackListTimer);
2245
+ baseData.updateTrackListTimer = setTimeout(function(){
2246
+ updateMediaTrackList.call(media, baseData);
2247
+ }, 9);
2248
+ }
2249
+ });
2250
+ });
2251
+
2252
+ if(Modernizr.track){
2253
+ $('video, audio').trigger('trackapichange');
2254
+ }
2255
+
2204
2256
  });