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){
@@ -2098,766 +2102,814 @@ jQuery.webshims.register('form-core', function($, webshims, window, document, un
2098
2102
  });
2099
2103
  }
2100
2104
 
2101
- });jQuery.webshims.register('track', function($, webshims, window, document, undefined){
2102
- var mediaelement = webshims.mediaelement;
2103
- var id = new Date().getTime();
2104
- var showTracks = {subtitles: 1, captions: 1};
2105
- var notImplemented = function(){
2106
- webshims.error('not implemented yet');
2107
- };
2108
-
2109
- var createEventTarget = function(obj){
2110
- var eventList = {};
2111
- obj.addEventListener = function(name, fn){
2112
- if(eventList[name]){
2113
- webshims.error('always use $.bind to the shimed event: '+ name +' already bound fn was: '+ eventList[name] +' your fn was: '+ fn);
2114
- }
2115
- eventList[name] = fn;
2116
-
2117
- };
2118
- obj.removeEventListener = function(name, fn){
2119
- if(eventList[name] && eventList[name] != fn){
2120
- webshims.error('always use $.bind/$.unbind to the shimed event: '+ name +' already bound fn was: '+ eventList[name] +' your fn was: '+ fn);
2121
- }
2122
- if(eventList[name]){
2123
- delete eventList[name];
2124
- }
2125
- };
2126
- return obj;
2127
- };
2128
-
2129
-
2130
- var cueListProto = {
2131
- getCueById: function(id){
2132
- var cue = null;
2133
- for(var i = 0, len = this.length; i < len; i++){
2134
- if(this[i].id === id){
2135
- cue = this[i];
2136
- break;
2137
- }
2138
- }
2139
- return cue;
2140
- }
2141
- };
2142
- var textTrackProto = {
2143
- shimActiveCues: null,
2144
- _shimActiveCues: null,
2145
- activeCues: null,
2146
- cues: null,
2147
- kind: 'subtitles',
2148
- label: '',
2149
- language: '',
2150
- mode: 'disabled',
2151
- readyState: 0,
2152
- oncuechange: null,
2153
- toString: function() {
2154
- return "[object TextTrack]";
2155
- },
2156
- addCue: function(cue){
2157
- if(!this.cues){
2158
- this.cues = mediaelement.createCueList();
2159
- } else {
2160
- var lastCue = this.cues[this.cues.length-1];
2161
- if(lastCue && lastCue.startTime > cue.startTime){
2162
- webshims.error("cue startTime higher than previous cue's startTime");
2163
- }
2164
- }
2165
- if(cue.track){
2166
- webshims.error("cue already part of a track element");
2167
- }
2168
- cue.track = this;
2169
- this.cues.push(cue);
2170
- },
2171
- removeCue: notImplemented,
2172
- DISABLED: 'disabled',
2173
- OFF: 'disabled',
2174
- HIDDEN: 'hidden',
2175
- SHOWING: 'showing',
2176
- ERROR: 3,
2177
- LOADED: 2,
2178
- LOADING: 1,
2179
- NONE: 0
2180
- };
2181
- var copyProps = ['kind', 'label', 'srclang'];
2182
-
2183
- var owns = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
2184
-
2185
- //ToDo: add/remove event
2186
- var updateMediaTrackList = function(baseData, trackList){
2187
- var removed = [];
2188
- var added = [];
2189
- var newTracks = [];
2190
- var i, len;
2191
- if(!baseData){
2192
- baseData = webshims.data(this, 'mediaelementBase') || webshims.data(this, 'mediaelementBase', {});
2193
- }
2194
-
2195
- if(!trackList){
2196
- baseData.blockTrackListUpdate = true;
2197
- trackList = $.prop(this, 'textTracks');
2198
- baseData.blockTrackListUpdate = false;
2199
- }
2200
-
2201
- clearTimeout(baseData.updateTrackListTimer);
2202
-
2203
- $('track', this).each(function(){
2204
- var track = $.prop(this, 'track');
2205
- newTracks.push(track);
2206
- if(trackList.indexOf(track) == -1){
2207
- added.push(track);
2208
- }
2209
- });
2210
-
2211
- if(baseData.scriptedTextTracks){
2212
- for(i = 0, len = baseData.scriptedTextTracks.length; i < len; i++){
2213
- newTracks.push(baseData.scriptedTextTracks[i]);
2214
- if(trackList.indexOf(baseData.scriptedTextTracks[i]) == -1){
2215
- added.push(baseData.scriptedTextTracks[i]);
2216
- }
2217
- }
2218
- }
2219
-
2220
- for(i = 0, len = trackList.length; i < len; i++){
2221
- if(newTracks.indexOf(trackList[i]) == -1){
2222
- removed.push(trackList[i]);
2223
- }
2224
- }
2225
-
2226
- if(removed.length || added.length){
2227
- trackList.splice(0);
2228
-
2229
- for(i = 0, len = newTracks.length; i < len; i++){
2230
- trackList.push(newTracks[i]);
2231
- }
2232
- for(i = 0, len = removed.length; i < len; i++){
2233
- $([trackList]).triggerHandler($.Event({type: 'removetrack', track: trackList, track: removed[i]}));
2234
- }
2235
- for(i = 0, len = added.length; i < len; i++){
2236
- $([trackList]).triggerHandler($.Event({type: 'addtrack', track: trackList, track: added[i]}));
2237
- }
2238
- if(baseData.scriptedTextTracks || removed.length){
2239
- $(this).triggerHandler('updatetrackdisplay');
2240
- }
2241
- }
2242
- };
2243
-
2244
- var refreshTrack = function(track, trackData){
2245
- var mode, kind;
2246
- if(!trackData){
2247
- trackData = webshims.data(track, 'trackData');
2248
- }
2249
- if(trackData && !trackData.isTriggering){
2250
- trackData.isTriggering = true;
2251
- mode = (trackData.track || {}).mode;
2252
- kind = (trackData.track || {}).kind;
2253
- setTimeout(function(){
2254
- if(mode !== (trackData.track || {}).mode || kind != (trackData.track || {}).kind){
2255
- if(!(trackData.track || {}).readyState){
2256
- $(track).triggerHandler('checktrackmode');
2257
- } else {
2258
- $(track).parent().triggerHandler('updatetrackdisplay');
2259
- }
2260
- }
2261
- trackData.isTriggering = false;
2262
-
2263
- }, 9);
2264
- }
2265
- };
2266
-
2267
- var emptyDiv = $('<div />')[0];
2268
- window.TextTrackCue = function(startTime, endTime, text){
2269
- if(arguments.length != 3){
2270
- webshims.error("wrong arguments.length for TextTrackCue.constructor");
2271
- }
2272
-
2273
- this.startTime = startTime;
2274
- this.endTime = endTime;
2275
- this.text = text;
2276
-
2277
- this.id = "";
2278
- this.pauseOnExit = false;
2279
-
2280
- createEventTarget(this);
2281
- };
2282
-
2283
- window.TextTrackCue.prototype = {
2284
-
2285
- onenter: null,
2286
- onexit: null,
2287
- pauseOnExit: false,
2288
- getCueAsHTML: function(){
2289
- var lastText = "";
2290
- var parsedText = "";
2291
- var fragment = document.createDocumentFragment();
2292
- var fn;
2293
- if(!owns(this, 'getCueAsHTML')){
2294
- fn = this.getCueAsHTML = function(){
2295
- var i, len;
2296
- if(lastText != this.text){
2297
- lastText = this.text;
2298
- parsedText = mediaelement.parseCueTextToHTML(lastText);
2299
- emptyDiv.innerHTML = parsedText;
2300
-
2301
- for(i = 0, len = emptyDiv.childNodes.length; i < len; i++){
2302
- fragment.appendChild(emptyDiv.childNodes[i].cloneNode(true));
2303
- }
2304
- }
2305
- return fragment.cloneNode(true);
2306
- };
2307
-
2308
- }
2309
- return fn ? fn.apply(this, arguments) : fragment.cloneNode(true);
2310
- },
2311
- track: null,
2312
-
2313
-
2314
- id: ''
2315
- //todo-->
2316
- // ,
2317
- // snapToLines: true,
2318
- // line: 'auto',
2319
- // size: 100,
2320
- // position: 50,
2321
- // vertical: '',
2322
- // align: 'middle'
2323
- };
2324
-
2325
-
2326
-
2327
-
2328
-
2329
- mediaelement.createCueList = function(){
2330
- return $.extend([], cueListProto);
2331
- };
2332
-
2333
- mediaelement.parseCueTextToHTML = (function(){
2334
- var tagSplits = /(<\/?[^>]+>)/ig;
2335
- var allowedTags = /^(?:c|v|ruby|rt|b|i|u)/;
2336
- var regEnd = /\<\s*\//;
2337
- var addToTemplate = function(localName, attribute, tag, html){
2338
- var ret;
2339
- if(regEnd.test(html)){
2340
- ret = '</'+ localName +'>';
2341
- } else {
2342
- tag.splice(0, 1);
2343
- ret = '<'+ localName +' '+ attribute +'="'+ (tag.join(' ').replace(/\"/g, '&#34;')) +'">';
2344
- }
2345
- return ret;
2346
- };
2347
- var replacer = function(html){
2348
- var tag = html.replace(/[<\/>]+/ig,"").split(/[\s\.]+/);
2349
- if(tag[0]){
2350
- tag[0] = tag[0].toLowerCase();
2351
- if(allowedTags.test(tag[0])){
2352
- if(tag[0] == 'c'){
2353
- html = addToTemplate('span', 'class', tag, html);
2354
- } else if(tag[0] == 'v'){
2355
- html = addToTemplate('q', 'title', tag, html);
2356
- }
2357
- } else {
2358
- html = "";
2359
- }
2360
- }
2361
- return html;
2362
- };
2363
-
2364
- return function(cueText){
2365
- return cueText.replace(tagSplits, replacer);
2366
- };
2367
- })();
2368
-
2369
- mediaelement.loadTextTrack = function(mediaelem, track, trackData, _default){
2370
- var loadEvents = 'play playing timeupdate updatetrackdisplay';
2371
- var obj = trackData.track;
2372
- var load = function(){
2373
- var src = $.prop(track, 'src');
2374
- var error;
2375
- var ajax;
2376
- if(obj.mode != 'disabled' && src && $.attr(track, 'src')){
2377
- $(mediaelem).unbind(loadEvents, load);
2378
- $(track).unbind('checktrackmode', load);
2379
- if(!obj.readyState){
2380
- error = function(){
2381
- obj.readyState = 3;
2382
- obj.cues = null;
2383
- obj.activeCues = obj.shimActiveCues = obj._shimActiveCues = null;
2384
- $(track).triggerHandler('error');
2385
- };
2386
- obj.readyState = 1;
2387
- try {
2388
- obj.cues = mediaelement.createCueList();
2389
- obj.activeCues = obj.shimActiveCues = obj._shimActiveCues = mediaelement.createCueList();
2390
- ajax = $.ajax({
2391
- dataType: 'text',
2392
- url: src,
2393
- success: function(text){
2394
- if(ajax.getResponseHeader('content-type') != 'text/vtt'){
2395
- webshims.error('set the mime-type of your WebVTT files to text/vtt. see: http://dev.w3.org/html5/webvtt/#text/vtt');
2396
- }
2397
- mediaelement.parseCaptions(text, obj, function(cues){
2398
- if(cues && 'length' in cues){
2399
- obj.readyState = 2;
2400
- $(track).triggerHandler('load');
2401
- $(mediaelem).triggerHandler('updatetrackdisplay');
2402
- } else {
2403
- error();
2404
- }
2405
- });
2406
-
2407
- },
2408
- error: error
2409
- });
2410
- } catch(er){
2411
- error();
2412
- webshims.warn(er);
2413
- }
2414
- }
2415
- }
2416
- };
2417
- obj.readyState = 0;
2418
- obj.shimActiveCues = null;
2419
- obj._shimActiveCues = null;
2420
- obj.activeCues = null;
2421
- obj.cues = null;
2422
- $(mediaelem).unbind(loadEvents, load);
2423
- $(track).unbind('checktrackmode', load);
2424
- $(mediaelem).bind(loadEvents, load);
2425
- $(track).bind('checktrackmode', load);
2426
- if(_default){
2427
- obj.mode = showTracks[obj.kind] ? 'showing' : 'hidden';
2428
- load();
2429
- }
2430
- };
2431
-
2432
- mediaelement.createTextTrack = function(mediaelem, track){
2433
- var obj, trackData;
2434
- if(track.nodeName){
2435
- trackData = webshims.data(track, 'trackData');
2436
-
2437
- if(trackData){
2438
- refreshTrack(track, trackData);
2439
- obj = trackData.track;
2440
- }
2441
- }
2442
-
2443
- if(!obj){
2444
- obj = createEventTarget(webshims.objectCreate(textTrackProto));
2445
- copyProps.forEach(function(copyProp){
2446
- var prop = $.prop(track, copyProp);
2447
- if(prop){
2448
- if(copyProp == 'srclang'){
2449
- copyProp = 'language';
2450
- }
2451
- obj[copyProp] = prop;
2452
- }
2453
- });
2454
-
2455
-
2456
- if(track.nodeName){
2457
- trackData = webshims.data(track, 'trackData', {track: obj});
2458
- mediaelement.loadTextTrack(mediaelem, track, trackData, $.prop(track, 'default'));
2459
- } else {
2460
- obj.cues = mediaelement.createCueList();
2461
- obj.activeCues = obj._shimActiveCues = obj.shimActiveCues = mediaelement.createCueList();
2462
- obj.mode = 'hidden';
2463
- obj.readyState = 2;
2464
- }
2465
- }
2466
- return obj;
2467
- };
2468
-
2469
-
2470
- /*
2471
- taken from:
2472
- Captionator 0.5.1 [CaptionCrunch]
2473
- Christopher Giffard, 2011
2474
- Share and enjoy
2475
-
2476
- https://github.com/cgiffard/Captionator
2477
-
2478
- modified for webshims
2479
- */
2480
- mediaelement.parseCaptionChunk = (function(){
2481
- // Set up timestamp parsers
2482
- var WebVTTTimestampParser = /^(\d{2})?:?(\d{2}):(\d{2})\.(\d+)\s+\-\-\>\s+(\d{2})?:?(\d{2}):(\d{2})\.(\d+)\s*(.*)/;
2483
- var GoogleTimestampParser = /^([\d\.]+)\s+\+([\d\.]+)\s*(.*)/;
2484
- var WebVTTDEFAULTSCueParser = /^(DEFAULTS|DEFAULT)\s+\-\-\>\s+(.*)/g;
2485
- var WebVTTSTYLECueParser = /^(STYLE|STYLES)\s+\-\-\>\s*\n([\s\S]*)/g;
2486
- var WebVTTCOMMENTCueParser = /^(COMMENT|COMMENTS)\s+\-\-\>\s+(.*)/g;
2487
-
2488
- return function(subtitleElement,objectCount){
2489
- var cueDefaults = [];
2490
-
2491
- var subtitleParts, timeIn, timeOut, html, timeData, subtitlePartIndex, cueSettings = "", id, specialCueData;
2492
- var timestampMatch, tmpCue;
2493
-
2494
- // WebVTT Special Cue Logic
2495
- if ((specialCueData = WebVTTDEFAULTSCueParser.exec(subtitleElement))) {
2496
- // cueDefaults = specialCueData.slice(2).join("");
2497
- // cueDefaults = cueDefaults.split(/\s+/g).filter(function(def) { return def && !!def.length; });
2498
- return null;
2499
- } else if ((specialCueData = WebVTTSTYLECueParser.exec(subtitleElement))) {
2500
- return null;
2501
- } else if ((specialCueData = WebVTTCOMMENTCueParser.exec(subtitleElement))) {
2502
- return null; // At this stage, we don't want to do anything with these.
2503
- }
2504
-
2505
- subtitleParts = subtitleElement.split(/\n/g);
2506
-
2507
- // Trim off any blank lines (logically, should only be max. one, but loop to be sure)
2508
- while (!subtitleParts[0].replace(/\s+/ig,"").length && subtitleParts.length > 0) {
2509
- subtitleParts.shift();
2510
- }
2511
-
2512
- if (subtitleParts[0].match(/^\s*[a-z0-9]+\s*$/ig)) {
2513
- // The identifier becomes the cue ID (when *we* load the cues from file. Programatically created cues can have an ID of whatever.)
2514
- id = String(subtitleParts.shift().replace(/\s*/ig,""));
2515
- }
2516
-
2517
- for (subtitlePartIndex = 0; subtitlePartIndex < subtitleParts.length; subtitlePartIndex ++) {
2518
- var timestamp = subtitleParts[subtitlePartIndex];
2519
-
2520
- if ((timestampMatch = WebVTTTimestampParser.exec(timestamp))) {
2521
-
2522
- // WebVTT
2523
-
2524
- timeData = timestampMatch.slice(1);
2525
-
2526
- timeIn = parseInt((timeData[0]||0) * 60 * 60,10) + // Hours
2527
- parseInt((timeData[1]||0) * 60,10) + // Minutes
2528
- parseInt((timeData[2]||0),10) + // Seconds
2529
- parseFloat("0." + (timeData[3]||0)); // MS
2530
-
2531
- timeOut = parseInt((timeData[4]||0) * 60 * 60,10) + // Hours
2532
- parseInt((timeData[5]||0) * 60,10) + // Minutes
2533
- parseInt((timeData[6]||0),10) + // Seconds
2534
- parseFloat("0." + (timeData[7]||0)); // MS
2535
- /*
2536
- if (timeData[8]) {
2537
- cueSettings = timeData[8];
2538
- }
2539
- */
2540
- }
2541
-
2542
- // We've got the timestamp - return all the other unmatched lines as the raw subtitle data
2543
- subtitleParts = subtitleParts.slice(0,subtitlePartIndex).concat(subtitleParts.slice(subtitlePartIndex+1));
2544
- break;
2545
- }
2546
-
2547
- if (!timeIn && !timeOut) {
2548
- // We didn't extract any time information. Assume the cue is invalid!
2549
- return null;
2550
- }
2551
- /*
2552
- // Consolidate cue settings, convert defaults to object
2553
- var compositeCueSettings =
2554
- cueDefaults
2555
- .reduce(function(previous,current,index,array){
2556
- previous[current.split(":")[0]] = current.split(":")[1];
2557
- return previous;
2558
- },{});
2559
-
2560
- // Loop through cue settings, replace defaults with cue specific settings if they exist
2561
- compositeCueSettings =
2562
- cueSettings
2563
- .split(/\s+/g)
2564
- .filter(function(set) { return set && !!set.length; })
2565
- // Convert array to a key/val object
2566
- .reduce(function(previous,current,index,array){
2567
- previous[current.split(":")[0]] = current.split(":")[1];
2568
- return previous;
2569
- },compositeCueSettings);
2570
-
2571
- // Turn back into string like the TextTrackCue constructor expects
2572
- cueSettings = "";
2573
- for (var key in compositeCueSettings) {
2574
- if (compositeCueSettings.hasOwnProperty(key)) {
2575
- cueSettings += !!cueSettings.length ? " " : "";
2576
- cueSettings += key + ":" + compositeCueSettings[key];
2577
- }
2578
- }
2579
- */
2580
- // The remaining lines are the subtitle payload itself (after removing an ID if present, and the time);
2581
- html = subtitleParts.join("\n");
2582
- tmpCue = new TextTrackCue(timeIn, timeOut, html);
2583
- if(id){
2584
- tmpCue.id = id;
2585
- }
2586
- return tmpCue;
2587
- };
2588
- })();
2589
-
2590
- mediaelement.parseCaptions = function(captionData, track, complete) {
2591
- var subtitles = mediaelement.createCueList();
2592
- var cue, lazyProcess, regWevVTT;
2593
- var startDate;
2594
- var isWEBVTT;
2595
- if (captionData) {
2596
-
2597
- regWevVTT = /^WEBVTT(\s*FILE)?/ig;
2598
-
2599
- lazyProcess = function(i, len){
2600
-
2601
- for(; i < len; i++){
2602
- cue = captionData[i];
2603
- if(regWevVTT.test(cue)){
2604
- isWEBVTT = true;
2605
- } else if(cue.replace(/\s*/ig,"").length){
2606
- if(!isWEBVTT){
2607
- webshims.error('please use WebVTT format. This is the standard');
2608
- complete(null);
2609
- break;
2610
- }
2611
- cue = mediaelement.parseCaptionChunk(cue, i);
2612
- if(cue){
2613
- track.addCue(cue);
2614
- }
2615
- }
2616
- if(startDate < (new Date().getTime()) - 9){
2617
- i++;
2618
- setTimeout(function(){
2619
- startDate = new Date().getTime();
2620
- lazyProcess(i, len);
2621
- }, 90);
2622
-
2623
- break;
2624
- }
2625
- }
2626
- if(i >= len){
2627
- if(!isWEBVTT){
2628
- webshims.error('please use WebVTT format. This is the standard');
2629
- }
2630
- complete(track.cues);
2631
- }
2632
- };
2633
-
2634
- captionData = captionData.replace(/\r\n/g,"\n");
2635
-
2636
- setTimeout(function(){
2637
- captionData = captionData.replace(/\r/g,"\n");
2638
- setTimeout(function(){
2639
- startDate = new Date().getTime();
2640
- captionData = captionData.split(/\n\n+/g);
2641
- lazyProcess(0, captionData.length);
2642
- }, 9);
2643
- }, 9);
2644
-
2645
- } else {
2646
- webshims.error("Required parameter captionData not supplied.");
2647
- }
2648
- };
2649
-
2650
-
2651
- mediaelement.createTrackList = function(mediaelem, baseData){
2652
- baseData = baseData || webshims.data(mediaelem, 'mediaelementBase') || webshims.data(mediaelem, 'mediaelementBase', {});
2653
- if(!baseData.textTracks){
2654
- baseData.textTracks = [];
2655
- webshims.defineProperties(baseData.textTracks, {
2656
- onaddtrack: {value: null},
2657
- onremovetrack: {value: null}
2658
- });
2659
- createEventTarget(baseData.textTracks);
2660
- }
2661
- return baseData.textTracks;
2662
- };
2663
-
2664
- if(!Modernizr.track){
2665
- webshims.defineNodeNamesBooleanProperty(['track'], 'default');
2666
- webshims.reflectProperties(['track'], ['srclang', 'label']);
2667
-
2668
- webshims.defineNodeNameProperties('track', {
2669
- src: {
2670
- //attr: {},
2671
- reflect: true,
2672
- propType: 'src'
2673
- }
2674
- });
2675
- }
2676
-
2677
- webshims.defineNodeNameProperties('track', {
2678
- kind: {
2679
- attr: Modernizr.track ? {
2680
- set: function(value){
2681
- var trackData = webshims.data(this, 'trackData');
2682
- this.setAttribute('data-kind', value);
2683
- if(trackData){
2684
- trackData.attrKind = value;
2685
- }
2686
- },
2687
- get: function(){
2688
- var trackData = webshims.data(this, 'trackData');
2689
- if(trackData && ('attrKind' in trackData)){
2690
- return trackData.attrKind;
2691
- }
2692
- return this.getAttribute('kind');
2693
- }
2694
- } : {},
2695
- reflect: true,
2696
- propType: 'enumarated',
2697
- defaultValue: 'subtitles',
2698
- limitedTo: ['subtitles', 'captions', 'descriptions', 'chapters', 'metadata']
2699
- }
2700
- });
2701
-
2702
- webshims.onNodeNamesPropertyModify('track', 'kind', function(){
2703
- var trackData = webshims.data(this, 'trackData');
2704
- if(trackData){
2705
- trackData.track.kind = $.prop(this, 'kind');
2706
- refreshTrack(this, trackData);
2707
- }
2708
- });
2709
-
2710
- webshims.onNodeNamesPropertyModify('track', 'src', function(val){
2711
- if(val){
2712
- var data = webshims.data(this, 'trackData');
2713
- var media;
2714
- if(data){
2715
- media = $(this).closest('video, audio');
2716
- if(media[0]){
2717
- mediaelement.loadTextTrack(media, this, data);
2718
- }
2719
- }
2720
- }
2721
-
2722
- });
2723
-
2724
- //
2725
-
2726
- webshims.defineNodeNamesProperties(['track'], {
2727
- ERROR: {
2728
- value: 3
2729
- },
2730
- LOADED: {
2731
- value: 2
2732
- },
2733
- LOADING: {
2734
- value: 1
2735
- },
2736
- NONE: {
2737
- value: 0
2738
- },
2739
- readyState: {
2740
- get: function(){
2741
- return ($.prop(this, 'track') || {readyState: 0}).readyState;
2742
- },
2743
- writeable: false
2744
- },
2745
- track: {
2746
- get: function(){
2747
- return mediaelement.createTextTrack($(this).closest('audio, video')[0], this);
2748
- },
2749
- writeable: false
2750
- }
2751
- }, 'prop');
2752
-
2753
- webshims.defineNodeNamesProperties(['audio', 'video'], {
2754
- textTracks: {
2755
- get: function(){
2756
-
2757
- var media = this;
2758
- var baseData = webshims.data(media, 'mediaelementBase') || webshims.data(media, 'mediaelementBase', {});
2759
- var tracks = mediaelement.createTrackList(media, baseData);
2760
- if(!baseData.blockTrackListUpdate){
2761
- updateMediaTrackList.call(media, baseData, tracks);
2762
- }
2763
- return tracks;
2764
- },
2765
- writeable: false
2766
- },
2767
- addTextTrack: {
2768
- value: function(kind, label, lang){
2769
- var textTrack = mediaelement.createTextTrack(this, {
2770
- kind: kind || '',
2771
- label: label || '',
2772
- srclang: lang || ''
2773
- });
2774
- var baseData = webshims.data(this, 'mediaelementBase') || webshims.data(this, 'mediaelementBase', {});
2775
- if (!baseData.scriptedTextTracks) {
2776
- baseData.scriptedTextTracks = [];
2777
- }
2778
- baseData.scriptedTextTracks.push(textTrack);
2779
- updateMediaTrackList.call(this);
2780
- return textTrack;
2781
- }
2782
- }
2783
- }, 'prop');
2784
-
2785
-
2786
- $(document).bind('emptied ended updatetracklist', function(e){
2787
- if($(e.target).is('audio, video')){
2788
- var baseData = webshims.data(e.target, 'mediaelementBase');
2789
- if(baseData){
2790
- clearTimeout(baseData.updateTrackListTimer);
2791
- baseData.updateTrackListTimer = setTimeout(function(){
2792
- updateMediaTrackList.call(e.target, baseData);
2793
- }, 0);
2794
- }
2795
- }
2796
- });
2797
-
2798
- var getNativeReadyState = function(trackElem, textTrack){
2799
- return textTrack.readyState || trackElem.readyState;
2800
- };
2801
-
2802
- webshims.addReady(function(context, insertedElement){
2803
- var insertedMedia = insertedElement.filter('video, audio, track').closest('audio, video');
2804
- $('video, audio', context)
2805
- .add(insertedMedia)
2806
- .each(function(){
2807
- updateMediaTrackList.call(this);
2808
- })
2809
- .each(function(){
2810
- if(Modernizr.track){
2811
- var shimedTextTracks = $.prop(this, 'textTracks');
2812
- var origTextTracks = this.textTracks;
2813
- if(shimedTextTracks.length != origTextTracks.length){
2814
- webshims.error("textTracks couldn't be copied");
2815
- }
2816
-
2817
- $('track', this)
2818
- .each(function(){
2819
- var shimedTrack = $.prop(this, 'track');
2820
- var origTrack = this.track;
2821
- var kind;
2822
- var readyState;
2823
- if(origTrack){
2824
- kind = $.prop(this, 'kind');
2825
- readyState = getNativeReadyState(this, origTrack);
2826
- if (origTrack.mode || readyState) {
2827
- shimedTrack.mode = origTrack.mode;
2828
- }
2829
- //disable track from showing + remove UI
2830
- if(kind != 'descriptions'){
2831
- origTrack.mode = (typeof origTrack.mode == 'string') ? 'disabled' : 0;
2832
- this.kind = 'metadata';
2833
- $(this).attr({kind: kind});
2834
- }
2835
-
2836
- }
2837
- })
2838
- .bind('load error', function(e){
2839
- if(e.originalEvent){
2840
- e.stopImmediatePropagation();
2841
- }
2842
- })
2843
- ;
2844
- }
2845
- })
2846
- ;
2847
- insertedMedia.each(function(){
2848
- var media = this;
2849
- var baseData = webshims.data(media, 'mediaelementBase');
2850
- if(baseData){
2851
- clearTimeout(baseData.updateTrackListTimer);
2852
- baseData.updateTrackListTimer = setTimeout(function(){
2853
- updateMediaTrackList.call(media, baseData);
2854
- }, 9);
2855
- }
2856
- });
2857
- });
2858
-
2859
- if(Modernizr.track){
2860
- $('video, audio').trigger('trackapichange');
2861
- }
2862
-
2105
+ });jQuery.webshims.register('track', function($, webshims, window, document, undefined){
2106
+ var mediaelement = webshims.mediaelement;
2107
+ var id = new Date().getTime();
2108
+ //descriptions are not really shown, but they are inserted into the dom
2109
+ var showTracks = {subtitles: 1, captions: 1, descriptions: 1};
2110
+ var notImplemented = function(){
2111
+ webshims.error('not implemented yet');
2112
+ };
2113
+ var supportTrackMod = Modernizr.ES5 && Modernizr.objectAccessor;
2114
+ var createEventTarget = function(obj){
2115
+ var eventList = {};
2116
+ obj.addEventListener = function(name, fn){
2117
+ if(eventList[name]){
2118
+ webshims.error('always use $.bind to the shimed event: '+ name +' already bound fn was: '+ eventList[name] +' your fn was: '+ fn);
2119
+ }
2120
+ eventList[name] = fn;
2121
+
2122
+ };
2123
+ obj.removeEventListener = function(name, fn){
2124
+ if(eventList[name] && eventList[name] != fn){
2125
+ webshims.error('always use $.bind/$.unbind to the shimed event: '+ name +' already bound fn was: '+ eventList[name] +' your fn was: '+ fn);
2126
+ }
2127
+ if(eventList[name]){
2128
+ delete eventList[name];
2129
+ }
2130
+ };
2131
+ return obj;
2132
+ };
2133
+
2134
+
2135
+ var cueListProto = {
2136
+ getCueById: function(id){
2137
+ var cue = null;
2138
+ for(var i = 0, len = this.length; i < len; i++){
2139
+ if(this[i].id === id){
2140
+ cue = this[i];
2141
+ break;
2142
+ }
2143
+ }
2144
+ return cue;
2145
+ }
2146
+ };
2147
+
2148
+ var textTrackProto = {
2149
+ shimActiveCues: null,
2150
+ _shimActiveCues: null,
2151
+ activeCues: null,
2152
+ cues: null,
2153
+ kind: 'subtitles',
2154
+ label: '',
2155
+ language: '',
2156
+ mode: 'disabled',
2157
+ readyState: 0,
2158
+ oncuechange: null,
2159
+ toString: function() {
2160
+ return "[object TextTrack]";
2161
+ },
2162
+ addCue: function(cue){
2163
+ if(!this.cues){
2164
+ this.cues = mediaelement.createCueList();
2165
+ } else {
2166
+ var lastCue = this.cues[this.cues.length-1];
2167
+ if(lastCue && lastCue.startTime > cue.startTime){
2168
+ webshims.error("cue startTime higher than previous cue's startTime");
2169
+ }
2170
+ }
2171
+ if(cue.track && cue.track.removeCue){
2172
+ cue.track.removeCue(cue);
2173
+ }
2174
+ cue.track = this;
2175
+ this.cues.push(cue);
2176
+ },
2177
+ //ToDo: make it more dynamic
2178
+ removeCue: function(cue){
2179
+ var cues = this.cues || [];
2180
+ var i = 0;
2181
+ var len = cues.length;
2182
+ if(cue.track != this){
2183
+ webshims.error("cue not part of track");
2184
+ return;
2185
+ }
2186
+ for(; i < len; i++){
2187
+ if(cues[i] === cue){
2188
+ cues.splice(i, 1);
2189
+ cue.track = null;
2190
+ break;
2191
+ }
2192
+ }
2193
+ if(cue.track){
2194
+ webshims.error("cue not part of track");
2195
+ return;
2196
+ }
2197
+ },
2198
+ DISABLED: 'disabled',
2199
+ OFF: 'disabled',
2200
+ HIDDEN: 'hidden',
2201
+ SHOWING: 'showing',
2202
+ ERROR: 3,
2203
+ LOADED: 2,
2204
+ LOADING: 1,
2205
+ NONE: 0
2206
+ };
2207
+ var copyProps = ['kind', 'label', 'srclang'];
2208
+ var copyName = {srclang: 'language'};
2209
+
2210
+ var owns = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
2211
+
2212
+ var updateMediaTrackList = function(baseData, trackList){
2213
+ var removed = [];
2214
+ var added = [];
2215
+ var newTracks = [];
2216
+ var i, len;
2217
+ if(!baseData){
2218
+ baseData = webshims.data(this, 'mediaelementBase') || webshims.data(this, 'mediaelementBase', {});
2219
+ }
2220
+
2221
+ if(!trackList){
2222
+ baseData.blockTrackListUpdate = true;
2223
+ trackList = $.prop(this, 'textTracks');
2224
+ baseData.blockTrackListUpdate = false;
2225
+ }
2226
+
2227
+ clearTimeout(baseData.updateTrackListTimer);
2228
+
2229
+ $('track', this).each(function(){
2230
+ var track = $.prop(this, 'track');
2231
+ newTracks.push(track);
2232
+ if(trackList.indexOf(track) == -1){
2233
+ added.push(track);
2234
+ }
2235
+ });
2236
+
2237
+ if(baseData.scriptedTextTracks){
2238
+ for(i = 0, len = baseData.scriptedTextTracks.length; i < len; i++){
2239
+ newTracks.push(baseData.scriptedTextTracks[i]);
2240
+ if(trackList.indexOf(baseData.scriptedTextTracks[i]) == -1){
2241
+ added.push(baseData.scriptedTextTracks[i]);
2242
+ }
2243
+ }
2244
+ }
2245
+
2246
+ for(i = 0, len = trackList.length; i < len; i++){
2247
+ if(newTracks.indexOf(trackList[i]) == -1){
2248
+ removed.push(trackList[i]);
2249
+ }
2250
+ }
2251
+
2252
+ if(removed.length || added.length){
2253
+ trackList.splice(0);
2254
+
2255
+ for(i = 0, len = newTracks.length; i < len; i++){
2256
+ trackList.push(newTracks[i]);
2257
+ }
2258
+ for(i = 0, len = removed.length; i < len; i++){
2259
+ $([trackList]).triggerHandler($.Event({type: 'removetrack', track: trackList, track: removed[i]}));
2260
+ }
2261
+ for(i = 0, len = added.length; i < len; i++){
2262
+ $([trackList]).triggerHandler($.Event({type: 'addtrack', track: trackList, track: added[i]}));
2263
+ }
2264
+ if(baseData.scriptedTextTracks || removed.length){
2265
+ $(this).triggerHandler('updatetrackdisplay');
2266
+ }
2267
+ }
2268
+ };
2269
+
2270
+ var refreshTrack = function(track, trackData){
2271
+ if(!trackData){
2272
+ trackData = webshims.data(track, 'trackData');
2273
+ }
2274
+ if(trackData && !trackData.isTriggering){
2275
+ trackData.isTriggering = true;
2276
+ setTimeout(function(){
2277
+ if(!(trackData.track || {}).readyState){
2278
+ $(track).triggerHandler('checktrackmode');
2279
+ } else {
2280
+ $(track).closest('audio, video').triggerHandler('updatetrackdisplay');
2281
+ }
2282
+ trackData.isTriggering = false;
2283
+ }, 1);
2284
+ }
2285
+ };
2286
+
2287
+ var emptyDiv = $('<div />')[0];
2288
+ window.TextTrackCue = function(startTime, endTime, text){
2289
+ if(arguments.length != 3){
2290
+ webshims.error("wrong arguments.length for TextTrackCue.constructor");
2291
+ }
2292
+
2293
+ this.startTime = startTime;
2294
+ this.endTime = endTime;
2295
+ this.text = text;
2296
+
2297
+ this.id = "";
2298
+ this.pauseOnExit = false;
2299
+
2300
+ createEventTarget(this);
2301
+ };
2302
+
2303
+ window.TextTrackCue.prototype = {
2304
+
2305
+ onenter: null,
2306
+ onexit: null,
2307
+ pauseOnExit: false,
2308
+ getCueAsHTML: function(){
2309
+ var lastText = "";
2310
+ var parsedText = "";
2311
+ var fragment = document.createDocumentFragment();
2312
+ var fn;
2313
+ if(!owns(this, 'getCueAsHTML')){
2314
+ fn = this.getCueAsHTML = function(){
2315
+ var i, len;
2316
+ if(lastText != this.text){
2317
+ lastText = this.text;
2318
+ parsedText = mediaelement.parseCueTextToHTML(lastText);
2319
+ emptyDiv.innerHTML = parsedText;
2320
+
2321
+ for(i = 0, len = emptyDiv.childNodes.length; i < len; i++){
2322
+ fragment.appendChild(emptyDiv.childNodes[i].cloneNode(true));
2323
+ }
2324
+ }
2325
+ return fragment.cloneNode(true);
2326
+ };
2327
+
2328
+ }
2329
+ return fn ? fn.apply(this, arguments) : fragment.cloneNode(true);
2330
+ },
2331
+ track: null,
2332
+
2333
+
2334
+ id: ''
2335
+ //todo-->
2336
+ // ,
2337
+ // snapToLines: true,
2338
+ // line: 'auto',
2339
+ // size: 100,
2340
+ // position: 50,
2341
+ // vertical: '',
2342
+ // align: 'middle'
2343
+ };
2344
+
2345
+
2346
+
2347
+
2348
+
2349
+ mediaelement.createCueList = function(){
2350
+ return $.extend([], cueListProto);
2351
+ };
2352
+
2353
+ mediaelement.parseCueTextToHTML = (function(){
2354
+ var tagSplits = /(<\/?[^>]+>)/ig;
2355
+ var allowedTags = /^(?:c|v|ruby|rt|b|i|u)/;
2356
+ var regEnd = /\<\s*\//;
2357
+ var addToTemplate = function(localName, attribute, tag, html){
2358
+ var ret;
2359
+ if(regEnd.test(html)){
2360
+ ret = '</'+ localName +'>';
2361
+ } else {
2362
+ tag.splice(0, 1);
2363
+ ret = '<'+ localName +' '+ attribute +'="'+ (tag.join(' ').replace(/\"/g, '&#34;')) +'">';
2364
+ }
2365
+ return ret;
2366
+ };
2367
+ var replacer = function(html){
2368
+ var tag = html.replace(/[<\/>]+/ig,"").split(/[\s\.]+/);
2369
+ if(tag[0]){
2370
+ tag[0] = tag[0].toLowerCase();
2371
+ if(allowedTags.test(tag[0])){
2372
+ if(tag[0] == 'c'){
2373
+ html = addToTemplate('span', 'class', tag, html);
2374
+ } else if(tag[0] == 'v'){
2375
+ html = addToTemplate('q', 'title', tag, html);
2376
+ }
2377
+ } else {
2378
+ html = "";
2379
+ }
2380
+ }
2381
+ return html;
2382
+ };
2383
+
2384
+ return function(cueText){
2385
+ return cueText.replace(tagSplits, replacer);
2386
+ };
2387
+ })();
2388
+
2389
+ mediaelement.loadTextTrack = function(mediaelem, track, trackData, _default){
2390
+ var loadEvents = 'play playing timeupdate updatetrackdisplay';
2391
+ var obj = trackData.track;
2392
+ var load = function(){
2393
+ var src = $.prop(track, 'src');
2394
+ var error;
2395
+ var ajax;
2396
+ if(obj.mode != 'disabled' && src && $.attr(track, 'src')){
2397
+ $(mediaelem).unbind(loadEvents, load);
2398
+ $(track).unbind('checktrackmode', load);
2399
+ if(!obj.readyState){
2400
+ error = function(){
2401
+ obj.readyState = 3;
2402
+ obj.cues = null;
2403
+ obj.activeCues = obj.shimActiveCues = obj._shimActiveCues = null;
2404
+ $(track).triggerHandler('error');
2405
+ };
2406
+ obj.readyState = 1;
2407
+ try {
2408
+ obj.cues = mediaelement.createCueList();
2409
+ obj.activeCues = obj.shimActiveCues = obj._shimActiveCues = mediaelement.createCueList();
2410
+ ajax = $.ajax({
2411
+ dataType: 'text',
2412
+ url: src,
2413
+ success: function(text){
2414
+ if(ajax.getResponseHeader('content-type') != 'text/vtt'){
2415
+ webshims.error('set the mime-type of your WebVTT files to text/vtt. see: http://dev.w3.org/html5/webvtt/#text/vtt');
2416
+ }
2417
+ mediaelement.parseCaptions(text, obj, function(cues){
2418
+ if(cues && 'length' in cues){
2419
+ obj.readyState = 2;
2420
+ $(track).triggerHandler('load');
2421
+ $(mediaelem).triggerHandler('updatetrackdisplay');
2422
+ } else {
2423
+ error();
2424
+ }
2425
+ });
2426
+
2427
+ },
2428
+ error: error
2429
+ });
2430
+ } catch(er){
2431
+ error();
2432
+ webshims.warn(er);
2433
+ }
2434
+ }
2435
+ }
2436
+ };
2437
+ obj.readyState = 0;
2438
+ obj.shimActiveCues = null;
2439
+ obj._shimActiveCues = null;
2440
+ obj.activeCues = null;
2441
+ obj.cues = null;
2442
+ $(mediaelem).unbind(loadEvents, load);
2443
+ $(track).unbind('checktrackmode', load);
2444
+ $(mediaelem).bind(loadEvents, load);
2445
+ $(track).bind('checktrackmode', load);
2446
+ if(_default){
2447
+ obj.mode = showTracks[obj.kind] ? 'showing' : 'hidden';
2448
+ load();
2449
+ }
2450
+ };
2451
+
2452
+ mediaelement.createTextTrack = function(mediaelem, track){
2453
+ var obj, trackData;
2454
+ if(track.nodeName){
2455
+ trackData = webshims.data(track, 'trackData');
2456
+
2457
+ if(trackData){
2458
+ refreshTrack(track, trackData);
2459
+ obj = trackData.track;
2460
+ }
2461
+ }
2462
+
2463
+ if(!obj){
2464
+ obj = createEventTarget(webshims.objectCreate(textTrackProto));
2465
+
2466
+ if(!supportTrackMod){
2467
+ copyProps.forEach(function(copyProp){
2468
+ var prop = $.prop(track, copyProp);
2469
+ if(prop){
2470
+ obj[copyName[copyProp] || copyProp] = prop;
2471
+ }
2472
+ });
2473
+ }
2474
+
2475
+
2476
+ if(track.nodeName){
2477
+
2478
+ if(supportTrackMod){
2479
+ copyProps.forEach(function(copyProp){
2480
+ webshims.defineProperty(obj, copyName[copyProp] || copyProp, {
2481
+ get: function(){
2482
+ return $.prop(track, copyProp);
2483
+ }
2484
+ });
2485
+ });
2486
+ }
2487
+
2488
+ trackData = webshims.data(track, 'trackData', {track: obj});
2489
+ mediaelement.loadTextTrack(mediaelem, track, trackData, ($.prop(track, 'default') && $(track).siblings('track[default]').andSelf()[0] == track));
2490
+ } else {
2491
+ if(supportTrackMod){
2492
+ copyProps.forEach(function(copyProp){
2493
+ webshims.defineProperty(obj, copyName[copyProp] || copyProp, {
2494
+ value: track[copyProp],
2495
+ writeable: false
2496
+ });
2497
+ });
2498
+ }
2499
+ obj.cues = mediaelement.createCueList();
2500
+ obj.activeCues = obj._shimActiveCues = obj.shimActiveCues = mediaelement.createCueList();
2501
+ obj.mode = 'hidden';
2502
+ obj.readyState = 2;
2503
+ }
2504
+ }
2505
+ return obj;
2506
+ };
2507
+
2508
+
2509
+ /*
2510
+ taken from:
2511
+ Captionator 0.5.1 [CaptionCrunch]
2512
+ Christopher Giffard, 2011
2513
+ Share and enjoy
2514
+
2515
+ https://github.com/cgiffard/Captionator
2516
+
2517
+ modified for webshims
2518
+ */
2519
+ mediaelement.parseCaptionChunk = (function(){
2520
+ // Set up timestamp parsers
2521
+ var WebVTTTimestampParser = /^(\d{2})?:?(\d{2}):(\d{2})\.(\d+)\s+\-\-\>\s+(\d{2})?:?(\d{2}):(\d{2})\.(\d+)\s*(.*)/;
2522
+ var GoogleTimestampParser = /^([\d\.]+)\s+\+([\d\.]+)\s*(.*)/;
2523
+ var WebVTTDEFAULTSCueParser = /^(DEFAULTS|DEFAULT)\s+\-\-\>\s+(.*)/g;
2524
+ var WebVTTSTYLECueParser = /^(STYLE|STYLES)\s+\-\-\>\s*\n([\s\S]*)/g;
2525
+ var WebVTTCOMMENTCueParser = /^(COMMENT|COMMENTS)\s+\-\-\>\s+(.*)/g;
2526
+
2527
+ return function(subtitleElement,objectCount){
2528
+ var cueDefaults = [];
2529
+
2530
+ var subtitleParts, timeIn, timeOut, html, timeData, subtitlePartIndex, cueSettings = "", id, specialCueData;
2531
+ var timestampMatch, tmpCue;
2532
+
2533
+ // WebVTT Special Cue Logic
2534
+ if ((specialCueData = WebVTTDEFAULTSCueParser.exec(subtitleElement))) {
2535
+ // cueDefaults = specialCueData.slice(2).join("");
2536
+ // cueDefaults = cueDefaults.split(/\s+/g).filter(function(def) { return def && !!def.length; });
2537
+ return null;
2538
+ } else if ((specialCueData = WebVTTSTYLECueParser.exec(subtitleElement))) {
2539
+ return null;
2540
+ } else if ((specialCueData = WebVTTCOMMENTCueParser.exec(subtitleElement))) {
2541
+ return null; // At this stage, we don't want to do anything with these.
2542
+ }
2543
+
2544
+ subtitleParts = subtitleElement.split(/\n/g);
2545
+
2546
+ // Trim off any blank lines (logically, should only be max. one, but loop to be sure)
2547
+ while (!subtitleParts[0].replace(/\s+/ig,"").length && subtitleParts.length > 0) {
2548
+ subtitleParts.shift();
2549
+ }
2550
+
2551
+ if (subtitleParts[0].match(/^\s*[a-z0-9-\_]+\s*$/ig)) {
2552
+ // The identifier becomes the cue ID (when *we* load the cues from file. Programatically created cues can have an ID of whatever.)
2553
+ id = String(subtitleParts.shift().replace(/\s*/ig,""));
2554
+ }
2555
+
2556
+ for (subtitlePartIndex = 0; subtitlePartIndex < subtitleParts.length; subtitlePartIndex ++) {
2557
+ var timestamp = subtitleParts[subtitlePartIndex];
2558
+
2559
+ if ((timestampMatch = WebVTTTimestampParser.exec(timestamp))) {
2560
+
2561
+ // WebVTT
2562
+
2563
+ timeData = timestampMatch.slice(1);
2564
+
2565
+ timeIn = parseInt((timeData[0]||0) * 60 * 60,10) + // Hours
2566
+ parseInt((timeData[1]||0) * 60,10) + // Minutes
2567
+ parseInt((timeData[2]||0),10) + // Seconds
2568
+ parseFloat("0." + (timeData[3]||0)); // MS
2569
+
2570
+ timeOut = parseInt((timeData[4]||0) * 60 * 60,10) + // Hours
2571
+ parseInt((timeData[5]||0) * 60,10) + // Minutes
2572
+ parseInt((timeData[6]||0),10) + // Seconds
2573
+ parseFloat("0." + (timeData[7]||0)); // MS
2574
+ /*
2575
+ if (timeData[8]) {
2576
+ cueSettings = timeData[8];
2577
+ }
2578
+ */
2579
+ }
2580
+
2581
+ // We've got the timestamp - return all the other unmatched lines as the raw subtitle data
2582
+ subtitleParts = subtitleParts.slice(0,subtitlePartIndex).concat(subtitleParts.slice(subtitlePartIndex+1));
2583
+ break;
2584
+ }
2585
+
2586
+ if (!timeIn && !timeOut) {
2587
+ // We didn't extract any time information. Assume the cue is invalid!
2588
+ webshims.warn("couldn't extract time information: "+[timeIn, timeOut, subtitleParts.join("\n"), id].join(' ; '));
2589
+ return null;
2590
+ }
2591
+ /*
2592
+ // Consolidate cue settings, convert defaults to object
2593
+ var compositeCueSettings =
2594
+ cueDefaults
2595
+ .reduce(function(previous,current,index,array){
2596
+ previous[current.split(":")[0]] = current.split(":")[1];
2597
+ return previous;
2598
+ },{});
2599
+
2600
+ // Loop through cue settings, replace defaults with cue specific settings if they exist
2601
+ compositeCueSettings =
2602
+ cueSettings
2603
+ .split(/\s+/g)
2604
+ .filter(function(set) { return set && !!set.length; })
2605
+ // Convert array to a key/val object
2606
+ .reduce(function(previous,current,index,array){
2607
+ previous[current.split(":")[0]] = current.split(":")[1];
2608
+ return previous;
2609
+ },compositeCueSettings);
2610
+
2611
+ // Turn back into string like the TextTrackCue constructor expects
2612
+ cueSettings = "";
2613
+ for (var key in compositeCueSettings) {
2614
+ if (compositeCueSettings.hasOwnProperty(key)) {
2615
+ cueSettings += !!cueSettings.length ? " " : "";
2616
+ cueSettings += key + ":" + compositeCueSettings[key];
2617
+ }
2618
+ }
2619
+ */
2620
+ // The remaining lines are the subtitle payload itself (after removing an ID if present, and the time);
2621
+ html = subtitleParts.join("\n");
2622
+ tmpCue = new TextTrackCue(timeIn, timeOut, html);
2623
+ if(id){
2624
+ tmpCue.id = id;
2625
+ }
2626
+ return tmpCue;
2627
+ };
2628
+ })();
2629
+
2630
+ mediaelement.parseCaptions = function(captionData, track, complete) {
2631
+ var subtitles = mediaelement.createCueList();
2632
+ var cue, lazyProcess, regWevVTT;
2633
+ var startDate;
2634
+ var isWEBVTT;
2635
+ if (captionData) {
2636
+
2637
+ regWevVTT = /^WEBVTT(\s*FILE)?/ig;
2638
+
2639
+ lazyProcess = function(i, len){
2640
+
2641
+ for(; i < len; i++){
2642
+ cue = captionData[i];
2643
+ if(regWevVTT.test(cue)){
2644
+ isWEBVTT = true;
2645
+ } else if(cue.replace(/\s*/ig,"").length){
2646
+ if(!isWEBVTT){
2647
+ webshims.error('please use WebVTT format. This is the standard');
2648
+ complete(null);
2649
+ break;
2650
+ }
2651
+ cue = mediaelement.parseCaptionChunk(cue, i);
2652
+ if(cue){
2653
+ track.addCue(cue);
2654
+ }
2655
+ }
2656
+ if(startDate < (new Date().getTime()) - 30){
2657
+ i++;
2658
+ setTimeout(function(){
2659
+ startDate = new Date().getTime();
2660
+ lazyProcess(i, len);
2661
+ }, 90);
2662
+
2663
+ break;
2664
+ }
2665
+ }
2666
+ if(i >= len){
2667
+ if(!isWEBVTT){
2668
+ webshims.error('please use WebVTT format. This is the standard');
2669
+ }
2670
+ complete(track.cues);
2671
+ }
2672
+ };
2673
+
2674
+ captionData = captionData.replace(/\r\n/g,"\n");
2675
+
2676
+ setTimeout(function(){
2677
+ captionData = captionData.replace(/\r/g,"\n");
2678
+ setTimeout(function(){
2679
+ startDate = new Date().getTime();
2680
+ captionData = captionData.split(/\n\n+/g);
2681
+ lazyProcess(0, captionData.length);
2682
+ }, 9);
2683
+ }, 9);
2684
+
2685
+ } else {
2686
+ webshims.error("Required parameter captionData not supplied.");
2687
+ }
2688
+ };
2689
+
2690
+
2691
+ mediaelement.createTrackList = function(mediaelem, baseData){
2692
+ baseData = baseData || webshims.data(mediaelem, 'mediaelementBase') || webshims.data(mediaelem, 'mediaelementBase', {});
2693
+ if(!baseData.textTracks){
2694
+ baseData.textTracks = [];
2695
+ webshims.defineProperties(baseData.textTracks, {
2696
+ onaddtrack: {value: null},
2697
+ onremovetrack: {value: null}
2698
+ });
2699
+ createEventTarget(baseData.textTracks);
2700
+ }
2701
+ return baseData.textTracks;
2702
+ };
2703
+
2704
+ if(!Modernizr.track){
2705
+ webshims.defineNodeNamesBooleanProperty(['track'], 'default');
2706
+ webshims.reflectProperties(['track'], ['srclang', 'label']);
2707
+
2708
+ webshims.defineNodeNameProperties('track', {
2709
+ src: {
2710
+ //attr: {},
2711
+ reflect: true,
2712
+ propType: 'src'
2713
+ }
2714
+ });
2715
+ }
2716
+
2717
+ webshims.defineNodeNameProperties('track', {
2718
+ kind: {
2719
+ attr: Modernizr.track ? {
2720
+ set: function(value){
2721
+ var trackData = webshims.data(this, 'trackData');
2722
+ this.setAttribute('data-kind', value);
2723
+ if(trackData){
2724
+ trackData.attrKind = value;
2725
+ }
2726
+ },
2727
+ get: function(){
2728
+ var trackData = webshims.data(this, 'trackData');
2729
+ if(trackData && ('attrKind' in trackData)){
2730
+ return trackData.attrKind;
2731
+ }
2732
+ return this.getAttribute('kind');
2733
+ }
2734
+ } : {},
2735
+ reflect: true,
2736
+ propType: 'enumarated',
2737
+ defaultValue: 'subtitles',
2738
+ limitedTo: ['subtitles', 'captions', 'descriptions', 'chapters', 'metadata']
2739
+ }
2740
+ });
2741
+
2742
+ $.each(copyProps, function(i, copyProp){
2743
+ var name = copyName[copyProp] || copyProp;
2744
+ webshims.onNodeNamesPropertyModify('track', copyProp, function(){
2745
+ var trackData = webshims.data(this, 'trackData');
2746
+ var track = this;
2747
+ if(trackData){
2748
+ if(copyProp == 'kind'){
2749
+ refreshTrack(this, trackData);
2750
+ }
2751
+ if(!supportTrackMod){
2752
+ trackData.track[name] = $.prop(this, copyProp);
2753
+ }
2754
+ clearTimeout(trackData.changedTrackPropTimer);
2755
+ trackData.changedTrackPropTimer = setTimeout(function(){
2756
+ $(track).trigger('updatesubtitlestate');
2757
+ }, 1);
2758
+ }
2759
+ });
2760
+ });
2761
+
2762
+
2763
+ webshims.onNodeNamesPropertyModify('track', 'src', function(val){
2764
+ if(val){
2765
+ var data = webshims.data(this, 'trackData');
2766
+ var media;
2767
+ if(data){
2768
+ media = $(this).closest('video, audio');
2769
+ if(media[0]){
2770
+ mediaelement.loadTextTrack(media, this, data);
2771
+ }
2772
+ }
2773
+ }
2774
+
2775
+ });
2776
+
2777
+ //
2778
+
2779
+ webshims.defineNodeNamesProperties(['track'], {
2780
+ ERROR: {
2781
+ value: 3
2782
+ },
2783
+ LOADED: {
2784
+ value: 2
2785
+ },
2786
+ LOADING: {
2787
+ value: 1
2788
+ },
2789
+ NONE: {
2790
+ value: 0
2791
+ },
2792
+ readyState: {
2793
+ get: function(){
2794
+ return ($.prop(this, 'track') || {readyState: 0}).readyState;
2795
+ },
2796
+ writeable: false
2797
+ },
2798
+ track: {
2799
+ get: function(){
2800
+ return mediaelement.createTextTrack($(this).closest('audio, video')[0], this);
2801
+ },
2802
+ writeable: false
2803
+ }
2804
+ }, 'prop');
2805
+
2806
+ webshims.defineNodeNamesProperties(['audio', 'video'], {
2807
+ textTracks: {
2808
+ get: function(){
2809
+ var media = this;
2810
+ var baseData = webshims.data(media, 'mediaelementBase') || webshims.data(media, 'mediaelementBase', {});
2811
+ var tracks = mediaelement.createTrackList(media, baseData);
2812
+ if(!baseData.blockTrackListUpdate){
2813
+ updateMediaTrackList.call(media, baseData, tracks);
2814
+ }
2815
+ return tracks;
2816
+ },
2817
+ writeable: false
2818
+ },
2819
+ addTextTrack: {
2820
+ value: function(kind, label, lang){
2821
+ var textTrack = mediaelement.createTextTrack(this, {
2822
+ kind: kind || '',
2823
+ label: label || '',
2824
+ srclang: lang || ''
2825
+ });
2826
+ var baseData = webshims.data(this, 'mediaelementBase') || webshims.data(this, 'mediaelementBase', {});
2827
+ if (!baseData.scriptedTextTracks) {
2828
+ baseData.scriptedTextTracks = [];
2829
+ }
2830
+ baseData.scriptedTextTracks.push(textTrack);
2831
+ updateMediaTrackList.call(this);
2832
+ return textTrack;
2833
+ }
2834
+ }
2835
+ }, 'prop');
2836
+
2837
+
2838
+ $(document).bind('emptied ended updatetracklist', function(e){
2839
+ if($(e.target).is('audio, video')){
2840
+ var baseData = webshims.data(e.target, 'mediaelementBase');
2841
+ if(baseData){
2842
+ clearTimeout(baseData.updateTrackListTimer);
2843
+ baseData.updateTrackListTimer = setTimeout(function(){
2844
+ updateMediaTrackList.call(e.target, baseData);
2845
+ }, 0);
2846
+ }
2847
+ }
2848
+ });
2849
+
2850
+ var getNativeReadyState = function(trackElem, textTrack){
2851
+ return textTrack.readyState || trackElem.readyState;
2852
+ };
2853
+
2854
+ webshims.addReady(function(context, insertedElement){
2855
+ var insertedMedia = insertedElement.filter('video, audio, track').closest('audio, video');
2856
+ $('video, audio', context)
2857
+ .add(insertedMedia)
2858
+ .each(function(){
2859
+ updateMediaTrackList.call(this);
2860
+ })
2861
+ .each(function(){
2862
+ if(Modernizr.track){
2863
+ var shimedTextTracks = $.prop(this, 'textTracks');
2864
+ var origTextTracks = this.textTracks;
2865
+ if(shimedTextTracks.length != origTextTracks.length){
2866
+ webshims.error("textTracks couldn't be copied");
2867
+ }
2868
+
2869
+ $('track', this)
2870
+ .each(function(){
2871
+ var shimedTrack = $.prop(this, 'track');
2872
+ var origTrack = this.track;
2873
+ var kind;
2874
+ var readyState;
2875
+ if(origTrack){
2876
+ kind = $.prop(this, 'kind');
2877
+ readyState = getNativeReadyState(this, origTrack);
2878
+ if (origTrack.mode || readyState) {
2879
+ shimedTrack.mode = origTrack.mode;
2880
+ }
2881
+ //disable track from showing + remove UI
2882
+ if(kind != 'descriptions'){
2883
+ origTrack.mode = (typeof origTrack.mode == 'string') ? 'disabled' : 0;
2884
+ this.kind = 'metadata';
2885
+ $(this).attr({kind: kind});
2886
+ }
2887
+
2888
+ }
2889
+ })
2890
+ .bind('load error', function(e){
2891
+ if(e.originalEvent){
2892
+ e.stopImmediatePropagation();
2893
+ }
2894
+ })
2895
+ ;
2896
+ }
2897
+ })
2898
+ ;
2899
+ insertedMedia.each(function(){
2900
+ var media = this;
2901
+ var baseData = webshims.data(media, 'mediaelementBase');
2902
+ if(baseData){
2903
+ clearTimeout(baseData.updateTrackListTimer);
2904
+ baseData.updateTrackListTimer = setTimeout(function(){
2905
+ updateMediaTrackList.call(media, baseData);
2906
+ }, 9);
2907
+ }
2908
+ });
2909
+ });
2910
+
2911
+ if(Modernizr.track){
2912
+ $('video, audio').trigger('trackapichange');
2913
+ }
2914
+
2863
2915
  });