webshims-rails 1.12.3 → 1.12.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/lib/webshims-rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/webshims/polyfiller.js +75 -31
  4. data/vendor/assets/javascripts/webshims/shims/color-picker.js +14 -14
  5. data/vendor/assets/javascripts/webshims/shims/combos/1.js +83 -459
  6. data/vendor/assets/javascripts/webshims/shims/combos/10.js +92 -69
  7. data/vendor/assets/javascripts/webshims/shims/combos/11.js +90 -54
  8. data/vendor/assets/javascripts/webshims/shims/combos/12.js +104 -494
  9. data/vendor/assets/javascripts/webshims/shims/combos/13.js +66 -228
  10. data/vendor/assets/javascripts/webshims/shims/combos/14.js +2 -0
  11. data/vendor/assets/javascripts/webshims/shims/combos/15.js +42 -40
  12. data/vendor/assets/javascripts/webshims/shims/combos/16.js +105 -494
  13. data/vendor/assets/javascripts/webshims/shims/combos/17.js +90 -54
  14. data/vendor/assets/javascripts/webshims/shims/combos/18.js +90 -54
  15. data/vendor/assets/javascripts/webshims/shims/combos/19.js +123 -471
  16. data/vendor/assets/javascripts/webshims/shims/combos/2.js +85 -474
  17. data/vendor/assets/javascripts/webshims/shims/combos/20.js +85 -205
  18. data/vendor/assets/javascripts/webshims/shims/combos/21.js +103 -45
  19. data/vendor/assets/javascripts/webshims/shims/combos/22.js +41 -40
  20. data/vendor/assets/javascripts/webshims/shims/combos/23.js +63 -454
  21. data/vendor/assets/javascripts/webshims/shims/combos/24.js +52 -36
  22. data/vendor/assets/javascripts/webshims/shims/combos/25.js +123 -471
  23. data/vendor/assets/javascripts/webshims/shims/combos/26.js +2 -15
  24. data/vendor/assets/javascripts/webshims/shims/combos/27.js +38 -266
  25. data/vendor/assets/javascripts/webshims/shims/combos/28.js +20 -20
  26. data/vendor/assets/javascripts/webshims/shims/combos/3.js +24 -20
  27. data/vendor/assets/javascripts/webshims/shims/combos/30.js +24 -20
  28. data/vendor/assets/javascripts/webshims/shims/combos/31.js +22 -20
  29. data/vendor/assets/javascripts/webshims/shims/combos/4.js +4 -15
  30. data/vendor/assets/javascripts/webshims/shims/combos/5.js +90 -54
  31. data/vendor/assets/javascripts/webshims/shims/combos/6.js +90 -54
  32. data/vendor/assets/javascripts/webshims/shims/combos/7.js +87 -474
  33. data/vendor/assets/javascripts/webshims/shims/combos/8.js +87 -474
  34. data/vendor/assets/javascripts/webshims/shims/combos/9.js +92 -69
  35. data/vendor/assets/javascripts/webshims/shims/combos/99.js +1724 -0
  36. data/vendor/assets/javascripts/webshims/shims/dom-extend.js +2 -15
  37. data/vendor/assets/javascripts/webshims/shims/form-core.js +19 -4
  38. data/vendor/assets/javascripts/webshims/shims/form-datalist-lazy.js +39 -5
  39. data/vendor/assets/javascripts/webshims/shims/form-message.js +2 -0
  40. data/vendor/assets/javascripts/webshims/shims/form-number-date-ui.js +69 -37
  41. data/vendor/assets/javascripts/webshims/shims/form-shim-extend.js +18 -20
  42. data/vendor/assets/javascripts/webshims/shims/form-shim-extend2.js +34 -16
  43. data/vendor/assets/javascripts/webshims/shims/form-validation.js +12 -9
  44. data/vendor/assets/javascripts/webshims/shims/form-validators.js +21 -5
  45. data/vendor/assets/javascripts/webshims/shims/forms-picker.js +16 -13
  46. data/vendor/assets/javascripts/webshims/shims/geolocation.js +3 -3
  47. data/vendor/assets/javascripts/webshims/shims/jajax.js +1262 -0
  48. data/vendor/assets/javascripts/webshims/shims/jme/b.js +576 -0
  49. data/vendor/assets/javascripts/webshims/shims/jme/c.js +1148 -0
  50. data/vendor/assets/javascripts/webshims/shims/jme/controls.css +373 -0
  51. data/vendor/assets/javascripts/webshims/shims/jme/controls.scss +711 -0
  52. data/vendor/assets/javascripts/webshims/shims/jme/jme.eot +0 -0
  53. data/vendor/assets/javascripts/webshims/shims/jme/jme.svg +36 -0
  54. data/vendor/assets/javascripts/webshims/shims/jme/jme.ttf +0 -0
  55. data/vendor/assets/javascripts/webshims/shims/jme/jme.woff +0 -0
  56. data/vendor/assets/javascripts/webshims/shims/jpicker/jpicker.css +16 -18
  57. data/vendor/assets/javascripts/webshims/shims/mediaelement-core.js +25 -188
  58. data/vendor/assets/javascripts/webshims/shims/mediaelement-jaris.js +58 -2
  59. data/vendor/assets/javascripts/webshims/shims/mediaelement-native-fix.js +130 -66
  60. data/vendor/assets/javascripts/webshims/shims/range-ui.js +21 -17
  61. data/vendor/assets/javascripts/webshims/shims/sizzle.js +1634 -1613
  62. data/vendor/assets/javascripts/webshims/shims/styles/forms-ext.css +5 -5
  63. data/vendor/assets/javascripts/webshims/shims/styles/scss/shim.scss +5 -1
  64. data/vendor/assets/javascripts/webshims/shims/styles/shim.css +13 -9
  65. data/vendor/assets/javascripts/webshims/shims/swfmini-embed.js +136 -0
  66. data/vendor/assets/javascripts/webshims/shims/swfmini.js +38 -266
  67. data/vendor/assets/javascripts/webshims/shims/track-ui.js +1 -3
  68. data/vendor/assets/javascripts/webshims/shims/track.js +41 -40
  69. metadata +13 -2
@@ -0,0 +1,1148 @@
1
+ webshims.register('mediacontrols', function($, webshims, window, doc, undefined, options){
2
+ "use strict";
3
+ var pseudoClasses = 'pseudoClasses';
4
+ var baseSelector = webshims.cfg.mediaelement.jme.selector;
5
+
6
+ var playStates = {
7
+ play: 1,
8
+ playing: 1
9
+ };
10
+
11
+ var pauseStates = {
12
+ pause: 1,
13
+ ended: 1
14
+ };
15
+
16
+ var loadRange = function(){
17
+ webshims.loader.loadList(['range-ui']);
18
+ };
19
+ var onSliderReady = function(fn){
20
+ loadRange();
21
+ webshims.ready('range-ui', fn);
22
+ };
23
+
24
+ var btnStructure = '<button class="{%class%}" type="button" aria-label="{%text%}"></button>';
25
+ var defaultStructure = '<div class="{%class%}"></div>';
26
+ var slideStructure = '<div class="{%class%}"></div>';
27
+ var ns = $.jme.classNS;
28
+ var noVolumeClass = (function(){
29
+ var audio;
30
+ var ret = '';
31
+ if(typeof window.Audio == 'function'){
32
+ audio = new Audio();
33
+ audio.volume = 0.55;
34
+ ret = audio.volume = 0.55 ? '' : ' no-volume-api';
35
+ }
36
+ return ret;
37
+ })();
38
+
39
+
40
+
41
+
42
+ $.jme.defineProp('controlbar', {
43
+ set: function(elem, value){
44
+ value = !!value;
45
+ var data = $.jme.data(elem);
46
+ var controlBar = $('div.jme-mediaoverlay, div.jme-controlbar', data.player);
47
+ var mediaControls = $.jme.plugins["media-controls"] ;
48
+ var structure = '';
49
+ var controls;
50
+ if(value && !controlBar[0]){
51
+ if(data._controlbar){
52
+ data._controlbar.appendTo(data.player);
53
+ } else {
54
+ data.media.prop('controls', false);
55
+ $.each(mediaControls.pluginOrder, function(i, name){
56
+ var plugin = $.jme.plugins[name];
57
+ if(plugin && plugin.structure){
58
+ structure += plugin.structure.replace('{%class%}', ns+name).replace('{%text%}', plugin.text || '');
59
+ } else if(name){
60
+ structure += name;
61
+ }
62
+ });
63
+ data._controlbar = $( mediaControls.barStructure );
64
+ controlBar = data._controlbar.find('div.jme-cb-box').addClass(ns+'media-controls');
65
+ controls = data._controlbar.filter('.jme-media-overlay').addClass(ns+'play-pause');
66
+ controls = controls.add( controlBar );
67
+ controls = controls.add( $(structure).appendTo(controlBar) );
68
+ data._controlbar.appendTo(data.player);
69
+ data.player.jmeFn('addControls', controls);
70
+ }
71
+
72
+ } else if(!value) {
73
+ controlBar.detach();
74
+ }
75
+ controlBar = null;
76
+ controls = null;
77
+ return value;
78
+ }
79
+ });
80
+
81
+ $.jme.defineMethod('updateControlbar', function(){
82
+ var timeSlider = $('.'+ $.jme.classNS +'time-slider', this);
83
+ if(timeSlider[0] && timeSlider.css('position') !== 'absolute'){
84
+ var width;
85
+ var elemWidths = 0;
86
+
87
+ width = Math.floor(timeSlider.parent().width()) - 0.2;
88
+ timeSlider
89
+ .siblings()
90
+ .each(function(){
91
+ if(this !== timeSlider[0] && $.css(this, 'position') !== 'absolute' && $.css(this, 'display') !== 'none'){
92
+ elemWidths += Math.ceil($(this).outerWidth(true)) + 0.1;
93
+ }
94
+ })
95
+ ;
96
+ timeSlider.width(Math.floor(width - elemWidths - Math.ceil(timeSlider.outerWidth(true) - timeSlider.width()) - 0.3));
97
+ }
98
+ });
99
+
100
+ $.jme.registerPlugin('media-controls', {
101
+ options: {
102
+ calculateTimerange: false
103
+ },
104
+ pluginOrder: ['<div class="play-pause-container">', 'play-pause', '</div>', '<div class="currenttime-container">', 'currenttime-display', '</div>', '<div class="progress-container">', 'time-slider', '</div>', '<div class="duration-container">', 'duration-display', '</div>', '<div class="mute-container">', 'mute-unmute', '</div>', '<div class="volume-container">', 'volume-slider', '</div>', '<div class="subtitle-container">', '<div class="subtitle-controls">', 'captions', '</div>', '</div>', '<div class="fullscreen-container">', 'fullscreen', '</div>'],
105
+ barStructure: '<div class="jme-media-overlay"></div><div class="jme-controlbar'+ noVolumeClass +'" tabindex="-1"><div class="jme-cb-box"></div></div>',
106
+ _create: function(control, media, base, options){
107
+ var timer;
108
+ var update = function(){
109
+ clearTimeout(timer);
110
+ control.jmeFn('updateControlbar');
111
+ timer = setTimeout(function(){
112
+ control.jmeFn('updateControlbar');
113
+ }, 9);
114
+ };
115
+ if(options.calculateTimerange){
116
+ setTimeout(function(){
117
+ media.on('loadedmetadata volumechange play pause ended emptied', update);
118
+ base.on('updatetimeformat controlsadded controlschanged playerdimensionchange', update);
119
+ $(window).on('resize emchange', update);
120
+ }, 1);
121
+ update();
122
+ }
123
+ }
124
+ });
125
+
126
+ $.jme.registerPlugin('play-pause', {
127
+ pseudoClasses: {
128
+ play: 'state-paused',
129
+ pause: 'state-playing'
130
+ },
131
+ structure: btnStructure,
132
+ text: 'play / pause',
133
+ _create: function(control, media){
134
+ var textFn = $.jme.getButtonText(control, [this[pseudoClasses].play, this[pseudoClasses].pause]);
135
+
136
+ media
137
+ .on('play playing ended pause updateJMEState', function(e){
138
+ var state = e.type;
139
+ if(playStates[state]){
140
+ state = 1;
141
+ } else if(pauseStates[state]) {
142
+ state = 0;
143
+ } else {
144
+ state = (media.jmeProp('isPlaying') )? 1 : 0;
145
+ }
146
+ textFn(state);
147
+ })
148
+ .triggerHandler('updateJMEState')
149
+ ;
150
+ control.on((control.is('select')) ? 'change' : 'click', function(e){
151
+ media.jmeFn('togglePlay');
152
+ e.stopPropagation();
153
+ });
154
+
155
+ }
156
+ });
157
+
158
+ $.jme.registerPlugin('mute-unmute', {
159
+ pseudoClasses: {
160
+ mute: 'state-mute',
161
+ unmute: 'state-unmute'
162
+ },
163
+ structure: btnStructure,
164
+ text: 'mute / unmute',
165
+ _create: function(control, media, base){
166
+ var textFn = $.jme.getButtonText(control, [this[pseudoClasses].mute, this[pseudoClasses].unmute]);
167
+ media
168
+ .on('volumechange updateJMEState', function(e){
169
+ textFn(media.prop('muted') ? 1 : 0);
170
+ })
171
+ .triggerHandler('updateJMEState')
172
+ ;
173
+
174
+ control.on((control.is('select')) ? 'change' : 'click', function(e){
175
+ media.prop('muted', !media.prop('muted'));
176
+ e.stopPropagation();
177
+ });
178
+
179
+ }
180
+ });
181
+
182
+ function createGetSetHandler(fns){
183
+ var throttleTimer;
184
+ var blocked;
185
+
186
+ if(fns.release === true){
187
+ fns.release = fns.set;
188
+ }
189
+ var getSetHelper = {
190
+ start: function(){
191
+ if(!blocked){
192
+ blocked = true;
193
+ if(fns.start){
194
+ fns.start();
195
+ }
196
+ }
197
+ },
198
+ release: function(){
199
+ if(blocked){
200
+ blocked = false;
201
+
202
+ if(fns.release){
203
+ fns.release();
204
+ }
205
+ }
206
+ },
207
+ get: function(){
208
+ if(blocked){return;}
209
+ return fns.get.apply(this, arguments);
210
+ },
211
+ set: function(){
212
+
213
+ var that = this;
214
+ var args = arguments;
215
+ getSetHelper.start();
216
+ clearTimeout(throttleTimer);
217
+ throttleTimer = setTimeout(function(){
218
+ fns.set.apply(that, args);
219
+ }, 33);
220
+ }
221
+ };
222
+ getSetHelper.fns = fns;
223
+ return getSetHelper;
224
+ }
225
+
226
+ $.jme.registerPlugin('volume-slider', {
227
+ structure: slideStructure,
228
+
229
+ _create: function(control, media, base){
230
+
231
+ var createFn = function(){
232
+ var api, volume;
233
+
234
+ volume = createGetSetHandler({
235
+ get: function(){
236
+ var volume = media.prop('volume');
237
+ if(volume !== undefined){
238
+ api.value(volume);
239
+ }
240
+ },
241
+ set: function(){
242
+ media.prop({
243
+ muted: false,
244
+ volume: api.options.value
245
+ });
246
+ },
247
+ release: true
248
+ });
249
+
250
+ api = control
251
+ .rangeUI({
252
+ min: 0,
253
+ max: 1,
254
+ //animate: true,
255
+ step: 'any',
256
+ input: volume.set,
257
+ change: volume.release,
258
+ baseClass: 'media-range'
259
+ })
260
+ .data('rangeUi')
261
+ ;
262
+ media.on('volumechange', volume.get);
263
+ };
264
+
265
+ onSliderReady(createFn);
266
+ }
267
+ });
268
+
269
+ $.jme.registerPlugin('time-slider', {
270
+ structure: slideStructure,
271
+ pseudoClasses: {
272
+ no: 'no-duration'
273
+ },
274
+ options: {
275
+ format: ['mm', 'ss']
276
+ },
277
+ _create: function(control, media, base){
278
+
279
+ var module = this;
280
+
281
+ var createFn = function(){
282
+ var time, durationChange, api, timeShow, wasPaused;
283
+ var hasDuration = $.jme.classNS+'has-duration';
284
+ var duration = media.prop('duration');
285
+
286
+ time = createGetSetHandler({
287
+ get: function(){
288
+ var time = media.prop('currentTime');
289
+ if(!isNaN(time)){
290
+ try {
291
+ api.value(time);
292
+ } catch(er){}
293
+ }
294
+
295
+ },
296
+ set: function(){
297
+ try {
298
+ media.prop('currentTime', api.options.value).triggerHandler('timechanged', [api.options.value]);
299
+ } catch(er){}
300
+ },
301
+ start: function(){
302
+ if(wasPaused == null){
303
+ wasPaused = media.prop('paused');
304
+ if(!wasPaused){
305
+ base._seekpause = true;
306
+ media.pause();
307
+ } else {
308
+ base._seekpause = false;
309
+ }
310
+ }
311
+ },
312
+ release: function(){
313
+ time.fns.set();
314
+ if(wasPaused === false){
315
+ media.play();
316
+ }
317
+ if('_seekpause' in base){
318
+ delete base._seekpause;
319
+ }
320
+ wasPaused = null;
321
+ }
322
+ });
323
+
324
+ durationChange = function(){
325
+ duration = media.prop('duration');
326
+ hasDuration = duration && isFinite(duration) && !isNaN(duration);
327
+ if(hasDuration){
328
+ api.disabled(false);
329
+ api.max(duration);
330
+
331
+ base.removeClass(module[pseudoClasses].no);
332
+ } else {
333
+ api.disabled(true);
334
+ api.max(Number.MAX_VALUE);
335
+ base.addClass(module[pseudoClasses].no);
336
+ }
337
+ };
338
+
339
+ api = control
340
+ .rangeUI({
341
+ min: 0,
342
+ value: media.prop('currentTime') || 0,
343
+ step: 'any',
344
+ input: time.set,
345
+ change: time.release,
346
+ textValue: function(val){
347
+ return media.jmeFn('formatTime', val);
348
+ },
349
+ baseClass: 'media-range'
350
+ })
351
+ .data('rangeUi')
352
+ ;
353
+
354
+ timeShow = $('<span class="'+ $.jme.classNS +'time-select" />').appendTo(control);
355
+
356
+ control
357
+ .on({
358
+ 'mouseenter': function(e){
359
+ if(hasDuration){
360
+ var widgetLeft = (control.offset() || {left: 0}).left;
361
+ var widgetWidth = control.innerWidth();
362
+ var posLeft = function(x){
363
+ var perc = (x - widgetLeft) / widgetWidth * 100;
364
+ timeShow
365
+ .html(media.jmeFn('formatTime', duration * perc / 100))
366
+ .css({left: perc+'%'})
367
+ ;
368
+ };
369
+
370
+ posLeft(e.pageX);
371
+ timeShow.addClass($.jme.classNS +'show-time-select');
372
+ control
373
+ .off('.jmetimeselect')
374
+ .on('mousemove.jmetimeselect', function(e){
375
+ posLeft(e.pageX);
376
+ })
377
+ ;
378
+ }
379
+ },
380
+ mouseleave: function(){
381
+ timeShow.removeClass($.jme.classNS +'show-time-select');
382
+ control.off('.jmetimeselect');
383
+ }
384
+ })
385
+ ;
386
+
387
+
388
+ media.on({
389
+ timeupdate: time.get,
390
+ emptied: function(){
391
+ durationChange();
392
+ api.value(0);
393
+ },
394
+ durationchange: durationChange
395
+ });
396
+
397
+ base.jmeFn('addControls', $('<div class="'+ $.jme.classNS +'buffer-progress" />').prependTo(control) );
398
+ durationChange();
399
+ };
400
+
401
+ onSliderReady(createFn);
402
+ }
403
+ });
404
+
405
+
406
+ $.jme.defineMethod('concerningRange', function(type, time){
407
+ var elem = this;
408
+ var ret = {start: 0, end: 0};
409
+ if(!type){
410
+ type = 'buffered';
411
+ }
412
+ type = $.prop(elem, type);
413
+
414
+ if(time == null){
415
+ time = $.prop(elem, 'currentTime');
416
+ }
417
+ if(!type || !('length' in type)){return ret;}
418
+ for(var i = 0, len = type.length; i < len; i++){
419
+ ret.start = type.start(i);
420
+ ret.end = type.end(i);
421
+ if(ret.start <= time && ret.end >= time){
422
+ break;
423
+ }
424
+ }
425
+ return ret;
426
+ });
427
+
428
+ $.jme.defineProp('progress', {
429
+ get: function(elem){
430
+ var data = $.jme.data(elem);
431
+ if(!data.media){return 0;}
432
+ var progress = data.media.jmeFn('concerningRange').end / data.media.prop('duration') * 100;
433
+ if(progress > 99.4){
434
+ progress = 100;
435
+ }
436
+ return progress || 0;
437
+ },
438
+ readonly: true
439
+ });
440
+
441
+ $.jme.registerPlugin('buffer-progress', {
442
+ _create: function(control, media, base, options){
443
+ var indicator = $('<div class="'+ $.jme.classNS +'buffer-progress-indicator" />').appendTo(control);
444
+ var drawBufferProgress = function(){
445
+ var progress = media.jmeProp('progress');
446
+
447
+
448
+ if(options.progress !== progress){
449
+ options.progress = progress;
450
+ indicator.css('width', progress +'%');
451
+ }
452
+ };
453
+ media.on({
454
+ progress: drawBufferProgress,
455
+ emptied: function(){
456
+ indicator.css('width', 0);
457
+ options.progress = 0;
458
+ },
459
+ playing: drawBufferProgress
460
+ });
461
+ drawBufferProgress();
462
+ }
463
+ });
464
+
465
+ var times = {
466
+ hh: 60000,
467
+ mm: 60,
468
+ ss: 1,
469
+ ms: 1/1000
470
+ };
471
+ var formatTime = function(sec, format){
472
+ var data;
473
+ if(!format){
474
+ format = ['mm', 'ss'];
475
+ }
476
+ if(sec == null){
477
+ data = $.jme.data(this);
478
+ sec = $.prop(data.media, 'duration');
479
+ }
480
+ if(!sec){
481
+ sec = 0;
482
+ }
483
+ var formated = [];
484
+ var frac;
485
+ for(var i = 0, len = format.length; i < len; i++){
486
+ if(format[i] == 'ms' && i == len -1 ){
487
+ frac = Math.round( (sec / times[format[i]]) / 10);
488
+ } else {
489
+ frac = parseInt(sec / times[format[i]], 10);
490
+ sec = sec % times[format[i]];
491
+ }
492
+ if(frac < 10){
493
+ frac = '0'+frac;
494
+ }
495
+ formated.push( frac );
496
+ }
497
+
498
+ return formated.join(':');
499
+ };
500
+ $.jme.defineMethod('formatTime', formatTime);
501
+
502
+ $.jme.defineProp('format', {
503
+ set: function(elem, format){
504
+ if(!$.isArray(format)){
505
+ format = format.split(':');
506
+ }
507
+ var data = $.jme.data(elem);
508
+ data.format = format;
509
+ $(elem).triggerHandler('updatetimeformat');
510
+ data.player.triggerHandler('updatetimeformat');
511
+ return 'noDataSet';
512
+ }
513
+ });
514
+
515
+ $.jme.registerPlugin('duration-display', {
516
+ structure: defaultStructure,
517
+ options: {
518
+ format: "mm:ss"
519
+ },
520
+ _create: function(control, media, base, options){
521
+ if(typeof options.format == 'string'){
522
+ options.format = options.format.split(':');
523
+ }
524
+ var showDuration = function(){
525
+ control.html(formatTime(media.prop('duration'), options.format));
526
+ };
527
+ media.on('durationchange emptied', showDuration);
528
+
529
+ control
530
+ .on('updatetimeformat', showDuration)
531
+ .jmeProp('format', options.format)
532
+ ;
533
+ }
534
+ });
535
+
536
+ $.jme.defineProp('countdown', {
537
+ set: function(elem, value){
538
+
539
+ var data = $.jme.data(elem);
540
+ data.countdown = !!value;
541
+ $(elem).triggerHandler('updatetimeformat');
542
+ data.player.triggerHandler('updatetimeformat');
543
+ return 'noDataSet';
544
+ }
545
+ });
546
+
547
+ $.jme.registerPlugin('currenttime-display', {
548
+ structure: defaultStructure,
549
+ options: {
550
+ format: "mm:ss",
551
+ countdown: false
552
+ },
553
+ _create: function(control, media, base, options){
554
+ if(typeof options.format == 'string'){
555
+ options.format = options.format.split(':');
556
+ }
557
+
558
+ var showTime = function(e){
559
+ var currentTime = media.prop('currentTime');
560
+ if(options.countdown){
561
+ currentTime = (media.prop('duration') || 0) - currentTime;
562
+ if(currentTime < 0.7){
563
+ currentTime = 0;
564
+ }
565
+ }
566
+ control.html(formatTime(currentTime, options.format));
567
+ };
568
+ media.on('timeupdate emptied durationchange', showTime);
569
+
570
+ control
571
+ .on('updatetimeformat', showTime)
572
+ .jmeProp('format', options.format)
573
+ ;
574
+ }
575
+ });
576
+
577
+
578
+ /**
579
+ * Added Poster Plugin
580
+ * @author mderting
581
+ */
582
+
583
+ /*
584
+ * the old technique wasn't fully bullet proof
585
+ * beside this, jme2 adovactes to use the new improved state-classes to handle visual effect on specific state (see CSS change)
586
+ */
587
+ $.jme.registerPlugin('poster-display', {
588
+ structure: '<div />',
589
+ options: {
590
+ },
591
+ _create: function(control, media, base, options){
592
+
593
+ /* Empty span element used for vertical centering in IE7 - thanks to Bruno Fassino.
594
+ * @see http://www.brunildo.org/test/img_center.html
595
+ */
596
+ var updatePoster = function(){
597
+ var poster = media.prop('poster');
598
+ if(poster){
599
+ control.html('<span></span><img src="'+ poster +'" class="'+ $.jme.classNS +'poster-image" />');
600
+ } else {
601
+ control.empty();
602
+ }
603
+ };
604
+ media.on('emptied', updatePoster);
605
+ updatePoster();
606
+ }
607
+ });
608
+
609
+ //taken from http://johndyer.name/native-fullscreen-javascript-api-plus-jquery-plugin/
610
+ $.jme.fullscreen = (function() {
611
+ var parentData;
612
+ var frameData;
613
+ var doc = document.documentElement;
614
+
615
+ var fullScreenApi = {
616
+ supportsFullScreen: Modernizr.prefixed('fullscreenEnabled', document, false) || Modernizr.prefixed('fullScreenEnabled', document, false),
617
+ isFullScreen: function() { return false; },
618
+ requestFullScreen: function(elem){
619
+ var tmpData;
620
+ parentData = [];
621
+ $(elem).parentsUntil('body').each(function(){
622
+ var pos = $.css(this, 'position');
623
+ var left = this.scrollLeft;
624
+ var top = this.scrollTop;
625
+ var changed;
626
+ tmpData = {elemStyle: this.style, elem: this};
627
+ if(pos !== 'static'){
628
+ changed = true;
629
+ tmpData.pos = tmpData.elemStyle.position;
630
+ this.style.position = 'static';
631
+ }
632
+ if(left){
633
+ changed = true;
634
+ tmpData.left = left;
635
+ }
636
+ if(top){
637
+ changed = true;
638
+ tmpData.top = top;
639
+ }
640
+ if(changed){
641
+ parentData.push(tmpData);
642
+ }
643
+ });
644
+ frameData = false;
645
+ try {
646
+ frameData = {elemStyle: frameElement.style, elem: frameElement, css: {}};
647
+ frameData.css.position = frameData.elemStyle.position;
648
+ frameData.elemStyle.position = 'fixed';
649
+ $.each(['top', 'left', 'right', 'bottom'], function(i, name){
650
+ frameData.css[name] = frameData.elemStyle[name];
651
+ frameData.elemStyle[name] = '0px';
652
+ });
653
+ $.each(['height', 'width'], function(i, name){
654
+ frameData.css[name] = frameData.elemStyle[name];
655
+ frameData.elemStyle[name] = '100%';
656
+ });
657
+ } catch(er){
658
+ frameData = false;
659
+ }
660
+
661
+ tmpData = null;
662
+ },
663
+ cancelFullScreen: function(){
664
+ if(parentData){
665
+ $.each(parentData, function(i, data){
666
+ if('pos' in data){
667
+ data.elemStyle.position = data.pos;
668
+ }
669
+ if(data.left){
670
+ data.elem.scrollLeft = data.left;
671
+ }
672
+ if(data.top){
673
+ data.elem.scrollTop = data.top;
674
+ }
675
+ data = null;
676
+ });
677
+ parentData = [];
678
+ }
679
+ if(frameData){
680
+ $.each(frameData.css, function(name, value){
681
+ frameData.elemStyle[name] = value;
682
+ });
683
+ frameData = false;
684
+ }
685
+ },
686
+ eventName: 'fullscreenchange',
687
+ exitName: 'exitFullscreen',
688
+ requestName: 'requestFullscreen',
689
+ elementName: 'fullscreenElement',
690
+ enabledName: ''
691
+ };
692
+
693
+ fullScreenApi.cancelFullWindow = fullScreenApi.cancelFullScreen;
694
+ fullScreenApi.requestFullWindow = fullScreenApi.requestFullScreen;
695
+
696
+ // update methods to do something useful
697
+ if (fullScreenApi.supportsFullScreen) {
698
+ fullScreenApi.enabledName = fullScreenApi.supportsFullScreen;
699
+ fullScreenApi.exitName = Modernizr.prefixed("exitFullscreen", document, false) || Modernizr.prefixed("cancelFullScreen", document, false);
700
+ fullScreenApi.elementName = Modernizr.prefixed("fullscreenElement", document, false) || Modernizr.prefixed("fullScreenElement", document, false);
701
+ fullScreenApi.supportsFullScreen = !!fullScreenApi.supportsFullScreen;
702
+ if(fullScreenApi.elementName != 'fullscreenElement' || fullScreenApi.exitName != 'exitFullscreen' || fullScreenApi.enabledName != 'fullscreenEnabled'){
703
+ $.each(Modernizr._domPrefixes, function(i, prefix){
704
+ var requestName = prefix+'RequestFullscreen';
705
+ if((requestName in doc) || ((requestName = prefix+'RequestFullScreen') && (requestName in doc))){
706
+ fullScreenApi.eventName = prefix + 'fullscreenchange';
707
+ fullScreenApi.requestName = requestName;
708
+ return false;
709
+ }
710
+ });
711
+ }
712
+
713
+ fullScreenApi.isFullScreen = function() {
714
+ return document[fullScreenApi.elementName];
715
+ };
716
+ fullScreenApi.requestFullScreen = function(el) {
717
+ return el[fullScreenApi.requestName]();
718
+ };
719
+ fullScreenApi.cancelFullScreen = function() {
720
+ return document[fullScreenApi.exitName]();
721
+ };
722
+ }
723
+
724
+ if(!window.Modernizr || !('fullscreen' in Modernizr)){
725
+ $('html').addClass(fullScreenApi.supportsFullScreen ? 'fullscreen' : 'no-fullscreen');
726
+ }
727
+
728
+ if(window.parent != window){
729
+ (function(){
730
+ try{
731
+ var frame = window.frameElement;
732
+ if (fullScreenApi.supportsFullScreen) {
733
+ if('allowfullscreen' in frame && !frame.allowfullscreen) {
734
+ frame.allowfullscreen = true;
735
+ } else {
736
+ if(frame.getAttribute('webkitallowfullscreen') == null){
737
+ frame.setAttribute('webkitallowfullscreen', '');
738
+ }
739
+ if(frame.getAttribute('allowfullscreen') == null){
740
+ frame.setAttribute('allowfullscreen', 'allowfullscreen');
741
+ }
742
+ }
743
+ }
744
+ } catch(er){
745
+ if(!fullScreenApi.supportsFullScreen){
746
+ $('html').addClass('no-fullwindow');
747
+ }
748
+ }
749
+ })();
750
+
751
+ }
752
+
753
+
754
+ return fullScreenApi;
755
+ })();
756
+
757
+ $.jme.defineProp('fullscreen', {
758
+ set: function(elem, value){
759
+ var data = $.jme.data(elem);
760
+
761
+ if((!data || !data.player) && !$(elem).hasClass($.jme.classNS+'player-fullscreen')){return 'noDataSet';}
762
+ if(value){
763
+ if(data.player.hasClass($.jme.classNS+'player-fullscreen')){return 'noDataSet';}
764
+
765
+ data.scrollPos = {
766
+ top: $(window).scrollTop(),
767
+ left: $(window).scrollLeft()
768
+ };
769
+
770
+ $(document)
771
+ .off('.jmefullscreen')
772
+ .on('keydown.jmefullscreen', function(e){
773
+ if(e.keyCode == 27){
774
+ data.player.jmeProp('fullscreen', false);
775
+ return false;
776
+ }
777
+ if(e.keyCode === 32 && !('form' in e.target)){
778
+ data.media.jmeFn('togglePlay');
779
+ return false;
780
+ }
781
+ })
782
+ ;
783
+
784
+
785
+ if(value == 'fullwindow'){
786
+ $.jme.fullscreen.requestFullWindow(data.player[0]);
787
+ } else {
788
+ try {
789
+ $.jme.fullscreen.requestFullScreen(data.player[0]);
790
+ } catch(er){}
791
+ }
792
+
793
+
794
+ $('html').addClass($.jme.classNS+'has-media-fullscreen');
795
+
796
+ data.player.addClass($.jme.classNS+'player-fullscreen');
797
+
798
+ data.media.addClass($.jme.classNS+'media-fullscreen');
799
+
800
+ $('button.play-pause', data.player).focus();
801
+
802
+ if($.jme.fullscreen.supportsFullScreen){
803
+ $(document)
804
+ .on($.jme.fullscreen.eventName+'.jmefullscreen', function(e){
805
+ var fullScreenElem = $.jme.fullscreen.isFullScreen();
806
+ if(fullScreenElem && elem == fullScreenElem){
807
+ data.media.trigger('playerdimensionchange', ['fullscreen']);
808
+ } else {
809
+ data.player.jmeProp('fullscreen', false);
810
+ }
811
+ })
812
+ ;
813
+
814
+ }
815
+ data.media.trigger('playerdimensionchange', ['fullwindow']);
816
+
817
+ } else {
818
+ if(data.player && !data.player.hasClass($.jme.classNS+'player-fullscreen')){return 'noDataSet';}
819
+ $(document).off('.jmefullscreen');
820
+ $('html').removeClass($.jme.classNS+'has-media-fullscreen');
821
+ if(data.player && data.media){
822
+ data.player.removeClass($.jme.classNS+'player-fullscreen');
823
+ data.media.removeClass($.jme.classNS+'media-fullscreen');
824
+ }
825
+ if($.jme.fullscreen.isFullScreen()){
826
+ try {
827
+ $.jme.fullscreen.cancelFullScreen();
828
+ } catch(er){}
829
+ } else {
830
+ $.jme.fullscreen.cancelFullWindow();
831
+ }
832
+
833
+ if(data.scrollPos){
834
+ $(window).scrollTop(data.scrollPos.top);
835
+ $(window).scrollLeft(data.scrollPos.left);
836
+ delete data.scrollPos;
837
+ }
838
+ if(data.media){
839
+ data.media.trigger('playerdimensionchange');
840
+ }
841
+ }
842
+ return 'noDataSet';
843
+ },
844
+ get: function(elem){
845
+ var data = $.jme.data(elem);
846
+ if(!data || !data.player){return;}
847
+ var fs = data.player.hasClass($.jme.classNS+'player-fullscreen');
848
+ if(!fs){return false;}
849
+ return $.jme.fullscreen.isFullScreen() || 'fullwindow';
850
+ }
851
+ });
852
+
853
+ $.jme.defineProp('autoplayfs');
854
+
855
+ $.jme.registerPlugin('fullscreen', {
856
+ pseudoClasses: {
857
+ enter: 'state-enterfullscreen',
858
+ exit: 'state-exitfullscreen'
859
+ },
860
+ options: {
861
+ fullscreen: true,
862
+ autoplayfs: false
863
+ },
864
+ structure: btnStructure,
865
+ text: 'enter fullscreen / exit fullscreen',
866
+ _create: function(control, media, base){
867
+ var textFn = $.jme.getButtonText(control, [this[pseudoClasses].enter, this[pseudoClasses].exit]);
868
+ var updateControl = function(){
869
+ textFn(base.hasClass($.jme.classNS+'player-fullscreen') ? 1 : 0);
870
+ };
871
+ var options = this.options;
872
+ var addDoubbleClick = function(){
873
+ $(base.data('jme').controlElements)
874
+ .filter('.jme-media-overlay')
875
+ .off('.dblfullscreen')
876
+ .on('dblclick.dblfullscreen', function(e){
877
+ base.jmeProp('fullscreen', !base.jmeProp('fullscreen'));
878
+ })
879
+ ;
880
+ };
881
+
882
+ base.on('controlsadded', addDoubbleClick);
883
+
884
+ base.on('playerdimensionchange', updateControl);
885
+
886
+ control.on((control.is('select')) ? 'change' : 'click', function(){
887
+ var value = base.hasClass($.jme.classNS+'player-fullscreen') ? false : options.fullscreen;
888
+ base.jmeProp('fullscreen', value);
889
+ if(value && options.autoplayfs){
890
+ media.jmeFn('play');
891
+ }
892
+ });
893
+ addDoubbleClick();
894
+ updateControl();
895
+ }
896
+ });
897
+
898
+
899
+ $.jme.ButtonMenu = function(button, menu, clickHandler){
900
+
901
+ this.button = $(button).attr({'aria-haspopup': 'true'});
902
+
903
+ this.clickHandler = clickHandler;
904
+
905
+ this.toggle = $.proxy(this, 'toggle');
906
+ this.keyIndex = $.proxy(this, 'keyIndex');
907
+ this._buttonClick = $.proxy(this, '_buttonClick');
908
+
909
+
910
+ this.addMenu(menu);
911
+ this._closeFocusOut();
912
+ this.button.on('click', this.toggle);
913
+
914
+ };
915
+
916
+ $.jme.ButtonMenu.prototype = {
917
+ addMenu: function(menu){
918
+ if(this.menu){
919
+ this.menu.remove();
920
+ }
921
+ this.menu = $(menu);
922
+ this.buttons = $('button', this.menu);
923
+ this.menu.insertAfter(this.button);
924
+ this.menu
925
+ .on('keydown', this.keyIndex)
926
+ .delegate('button', 'click', this._buttonClick)
927
+ ;
928
+ },
929
+ _closeFocusOut: function(){
930
+ var that = this;
931
+ var timer;
932
+ var stopFocusOut = function(){
933
+ clearTimeout(timer);
934
+ setTimeout(function(){
935
+ clearTimeout(timer);
936
+ }, 9);
937
+ };
938
+ this.menu
939
+ .parent()
940
+ .on('focusin', stopFocusOut)
941
+ .on('mousedown', stopFocusOut)
942
+ .on('focusout', function(e){
943
+ timer = setTimeout(function(){
944
+ that.hide();
945
+ }, 40);
946
+ })
947
+ ;
948
+ },
949
+ _buttonClick: function(e){
950
+ this.clickHandler(this.buttons.index(e.currentTarget), e.currentTarget);
951
+ this.hide();
952
+ },
953
+ keyIndex: function(e){
954
+ var dir = (e.keyCode == 40) ? 1 : (e.keyCode == 38) ? -1 : 0;
955
+ if(dir){
956
+ var buttons = this.buttons.not(':disabled');
957
+ var activeButton = buttons.filter(':focus');
958
+
959
+ activeButton = buttons[buttons.index(activeButton) + dir] || buttons.filter(dir > 0 ? ':first' : ':last');
960
+ activeButton.focus();
961
+ e.preventDefault();
962
+ }
963
+ },
964
+ show: function(){
965
+ if(this.isVisible){return;}
966
+ var buttons = this.buttons.not(':disabled');
967
+ this.isVisible = true;
968
+ this.menu.addClass('visible-menu');
969
+ try {
970
+ this.activeElement = document.activeElement || this.button[0];
971
+ } catch(er){
972
+ this.activeElement = this.button[0];
973
+ }
974
+
975
+ setTimeout(function(){
976
+ $(buttons.filter('[aria-checked="true"]')[0] || buttons[0]).focus();
977
+ }, 60);
978
+ },
979
+ toggle: function(){
980
+ this[this.isVisible ? 'hide' : 'show']();
981
+ },
982
+ hide: function(){
983
+ if(!this.isVisible){return;}
984
+ this.isVisible = false;
985
+ this.menu.removeClass('visible-menu');
986
+ if(this.activeElement){
987
+ try {
988
+ this.activeElement.focus();
989
+ } catch(er){}
990
+ }
991
+ this.activeElement = false;
992
+ }
993
+ };
994
+
995
+ var showKinds = {subtitles: 1, caption: 1};
996
+ var getTrackMenu = function(tracks){
997
+ var items = $.map(tracks, function(track){
998
+ var className = (track.kind == 'caption') ? 'caption-type' : 'subtitle-type';
999
+ var lang = track.language;
1000
+ lang = (lang) ? ' <span class="track-lang">'+ lang +'</span>' : '';
1001
+ return '<li class="'+ className +'" role="presentation"><button role="menuitemcheckbox">'+ track.label + lang +'</button></li>';
1002
+ })
1003
+ ;
1004
+ return '<div><ul>' + items.join('') +'</ul></div>';
1005
+ };
1006
+
1007
+
1008
+ $.jme.registerPlugin('captions', {
1009
+ pseudoClasses: {
1010
+ menu: 'subtitle-menu'
1011
+ },
1012
+ structure: btnStructure,
1013
+ text: 'subtitles',
1014
+ _create: function(control, media, base, options){
1015
+ var that = this;
1016
+
1017
+ var trackElems = media.find('track');
1018
+ var checkbox = $(control).clone().attr({role: 'checkbox'}).insertBefore(control);
1019
+
1020
+ base.attr('data-tracks', trackElems.length > 1 ? 'many' : trackElems.length);
1021
+ control.attr('aria-haspopup', 'true');
1022
+
1023
+ webshims.ready('track', function(){
1024
+ var menuObj, throttledUpdateMode;
1025
+ var tracks = [];
1026
+ var textTracks = media.prop('textTracks');
1027
+
1028
+ var throttledUpdate = (function(){
1029
+ var timer;
1030
+ var triggerTimer;
1031
+ return function(e){
1032
+ clearTimeout(timer);
1033
+ clearTimeout(triggerTimer);
1034
+ if(e.type == 'updatesubtitlestate'){
1035
+ triggerTimer = setTimeout(function(){
1036
+ media.trigger('updatetracklist');
1037
+ }, 0);
1038
+ }
1039
+ timer = setTimeout(updateTrackMenu, 19);
1040
+ };
1041
+ })();
1042
+
1043
+ function createSubtitleMenu(menu){
1044
+ var menuClick;
1045
+
1046
+ if(!menuObj){
1047
+ menuClick = function(index, button){
1048
+ if($.attr(button, 'aria-checked') == 'true'){
1049
+ tracks[index].mode = 'disabled';
1050
+ } else {
1051
+ $.each(tracks, function(i, track){
1052
+ track.mode = (i == index) ? 'showing' : 'disabled';
1053
+ });
1054
+ }
1055
+ media.prop('textTracks');
1056
+ updateMode();
1057
+ };
1058
+
1059
+ menuObj = new $.jme.ButtonMenu(control, menu, menuClick);
1060
+ checkbox.on('click', function(){
1061
+ menuClick(0, this);
1062
+ return false;
1063
+ });
1064
+ } else {
1065
+ menuObj.addMenu(menu);
1066
+ }
1067
+
1068
+ updateMode();
1069
+ }
1070
+
1071
+ function updateMode(){
1072
+ $('button', menuObj.menu).each(function(i){
1073
+ var checked = (tracks[i].mode == 'showing') ? 'true' : 'false';
1074
+ if(!i){
1075
+ checkbox.attr('aria-checked', checked);
1076
+ }
1077
+ $.attr(this, 'aria-checked', checked);
1078
+ });
1079
+ }
1080
+
1081
+ function updateTrackMenu(){
1082
+ tracks = [];
1083
+ $.each(textTracks, function(i, track){
1084
+ if(showKinds[track.kind] && track.readyState != 3){
1085
+ tracks.push(track);
1086
+ }
1087
+ });
1088
+
1089
+ base.attr('data-tracks', tracks.length > 1 ? 'many' : tracks.length);
1090
+
1091
+ if(tracks.length){
1092
+ createSubtitleMenu('<div class="'+that[pseudoClasses].menu +'" >'+ (getTrackMenu(tracks)) +'</div>');
1093
+
1094
+ $('span.jme-text, +label span.jme-text', checkbox).text((tracks[0].label || ' ') + (tracks[0].lang || ''));
1095
+
1096
+ if(!base.hasClass(that[pseudoClasses].hasTrack) || base.hasClass(that[pseudoClasses].noTrack)){
1097
+ control.prop('disabled', false);
1098
+ base.triggerHandler('controlschanged');
1099
+ }
1100
+
1101
+ } else if(!base.hasClass(that[pseudoClasses].noTrack) || base.hasClass(that[pseudoClasses].hasTrack)){
1102
+ control.prop('disabled', true);
1103
+ base
1104
+ .triggerHandler('controlschanged')
1105
+ ;
1106
+ }
1107
+ }
1108
+
1109
+ if(!textTracks){
1110
+ textTracks = [];
1111
+ updateTrackMenu();
1112
+ } else {
1113
+ throttledUpdateMode = (function(){
1114
+ var timer;
1115
+ return function(){
1116
+ clearTimeout(timer);
1117
+ timer = setTimeout(updateMode, 20);
1118
+ };
1119
+ })();
1120
+
1121
+ updateTrackMenu();
1122
+
1123
+ $([textTracks])
1124
+ .on('addtrack removetrack', throttledUpdate)
1125
+ .on('change', throttledUpdateMode)
1126
+ ;
1127
+
1128
+ base.on('updatesubtitlestate', throttledUpdate);
1129
+ media.on('updatetrackdisplay', throttledUpdateMode);
1130
+ }
1131
+
1132
+ });
1133
+ }
1134
+ });
1135
+
1136
+ $('.mediaplayer').each(function(){
1137
+ if(($.data(this, 'jme')|| {}).controlbar){
1138
+ $(this).jmeProp('controlbar', true);
1139
+ }
1140
+ });
1141
+
1142
+ webshims.ready('mediaelement', function(){
1143
+ webshims.addReady(function(context, insertedElement){
1144
+ $(baseSelector, context).add(insertedElement.filter(baseSelector)).jmeProp('controlbar', true);
1145
+ });
1146
+ });
1147
+ webshims.ready('WINDOWLOAD', loadRange);
1148
+ });