wai-website-theme 1.2 → 1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/_includes/backtotop.html +1 -1
  3. data/_includes/excol.html +1 -1
  4. data/_includes/feedback-box.html +13 -10
  5. data/_includes/footer.html +20 -6
  6. data/_includes/header.html +73 -35
  7. data/_includes/inpl.html +6 -0
  8. data/_includes/lang.html +7 -0
  9. data/_includes/link.html +92 -0
  10. data/_includes/menuitem.html +5 -3
  11. data/_includes/multilang-list-policy-links.html +1 -1
  12. data/_includes/navlist.html +1 -1
  13. data/_includes/prevnext.html +5 -4
  14. data/_includes/secondarynav.html +34 -6
  15. data/_includes/t.html +33 -0
  16. data/_includes/translation-note-msg.html +45 -0
  17. data/_includes/video-player.html +50 -9
  18. data/_layouts/default.html +32 -9
  19. data/_layouts/home.html +29 -5
  20. data/_layouts/news.html +27 -6
  21. data/_layouts/policy.html +27 -6
  22. data/_layouts/sidenav.html +27 -6
  23. data/_layouts/sidenavsidebar.html +27 -6
  24. data/assets/ableplayer/.gitattributes +0 -0
  25. data/assets/ableplayer/.gitignore +3 -1
  26. data/assets/ableplayer/Gruntfile.js +3 -1
  27. data/assets/ableplayer/LICENSE +0 -0
  28. data/assets/ableplayer/README.md +214 -170
  29. data/assets/ableplayer/_config.yml +1 -0
  30. data/assets/ableplayer/build/ableplayer.dist.js +2637 -744
  31. data/assets/ableplayer/build/ableplayer.js +2637 -744
  32. data/assets/ableplayer/build/ableplayer.min.css +2 -2
  33. data/assets/ableplayer/build/ableplayer.min.js +9 -7
  34. data/assets/ableplayer/button-icons/able-icons.svg +0 -0
  35. data/assets/ableplayer/button-icons/black/rabbit.png +0 -0
  36. data/assets/ableplayer/button-icons/black/turtle.png +0 -0
  37. data/assets/ableplayer/button-icons/white/rabbit.png +0 -0
  38. data/assets/ableplayer/button-icons/white/turtle.png +0 -0
  39. data/assets/ableplayer/images/wingrip.png +0 -0
  40. data/assets/ableplayer/package-lock.json +705 -0
  41. data/assets/ableplayer/package.json +11 -2
  42. data/assets/ableplayer/scripts/JQuery.doWhen.js +0 -0
  43. data/assets/ableplayer/scripts/ableplayer-base.js +129 -29
  44. data/assets/ableplayer/scripts/browser.js +0 -0
  45. data/assets/ableplayer/scripts/buildplayer.js +342 -262
  46. data/assets/ableplayer/scripts/caption.js +19 -0
  47. data/assets/ableplayer/scripts/chapters.js +21 -0
  48. data/assets/ableplayer/scripts/control.js +139 -56
  49. data/assets/ableplayer/scripts/description.js +0 -0
  50. data/assets/ableplayer/scripts/dialog.js +13 -13
  51. data/assets/ableplayer/scripts/dragdrop.js +102 -109
  52. data/assets/ableplayer/scripts/event.js +186 -83
  53. data/assets/ableplayer/scripts/initialize.js +261 -71
  54. data/assets/ableplayer/scripts/langs.js +4 -0
  55. data/assets/ableplayer/scripts/metadata.js +0 -0
  56. data/assets/ableplayer/scripts/misc.js +76 -7
  57. data/assets/ableplayer/scripts/preference.js +2 -2
  58. data/assets/ableplayer/scripts/search.js +10 -7
  59. data/assets/ableplayer/scripts/sign.js +0 -0
  60. data/assets/ableplayer/scripts/slider.js +35 -34
  61. data/assets/ableplayer/scripts/track.js +38 -22
  62. data/assets/ableplayer/scripts/transcript.js +15 -6
  63. data/assets/ableplayer/scripts/translation.js +29 -20
  64. data/assets/ableplayer/scripts/ttml2webvtt.js +87 -0
  65. data/assets/ableplayer/scripts/volume.js +16 -15
  66. data/assets/ableplayer/scripts/vts.js +1093 -0
  67. data/assets/ableplayer/scripts/webvtt.js +0 -0
  68. data/assets/ableplayer/scripts/youtube.js +16 -5
  69. data/assets/ableplayer/styles/ableplayer.css +125 -22
  70. data/assets/ableplayer/thirdparty/js.cookie.js +0 -0
  71. data/assets/ableplayer/thirdparty/modernizr.custom.js +0 -0
  72. data/assets/ableplayer/translations/ca.js +311 -1
  73. data/assets/ableplayer/translations/de.js +1 -1
  74. data/assets/ableplayer/translations/en.js +6 -0
  75. data/assets/ableplayer/translations/es.js +6 -0
  76. data/assets/ableplayer/translations/fr.js +6 -0
  77. data/assets/ableplayer/translations/he.js +311 -0
  78. data/assets/ableplayer/translations/it.js +7 -1
  79. data/assets/ableplayer/translations/ja.js +6 -0
  80. data/assets/ableplayer/translations/nb.js +311 -0
  81. data/assets/ableplayer/translations/nl.js +6 -0
  82. data/assets/ableplayer/translations/zh-tw.js +311 -0
  83. data/assets/css/style.css +1 -1
  84. data/assets/css/style.css.map +1 -1
  85. data/assets/fonts/{anonymouspro-bold.woff → anonymouspro/anonymouspro-bold.woff} +0 -0
  86. data/assets/fonts/{anonymouspro-bold.woff2 → anonymouspro/anonymouspro-bold.woff2} +0 -0
  87. data/assets/fonts/{anonymouspro-bolditalic.woff → anonymouspro/anonymouspro-bolditalic.woff} +0 -0
  88. data/assets/fonts/{anonymouspro-bolditalic.woff2 → anonymouspro/anonymouspro-bolditalic.woff2} +0 -0
  89. data/assets/fonts/{anonymouspro-italic.woff → anonymouspro/anonymouspro-italic.woff} +0 -0
  90. data/assets/fonts/{anonymouspro-italic.woff2 → anonymouspro/anonymouspro-italic.woff2} +0 -0
  91. data/assets/fonts/{anonymouspro-regular.woff → anonymouspro/anonymouspro-regular.woff} +0 -0
  92. data/assets/fonts/{anonymouspro-regular.woff2 → anonymouspro/anonymouspro-regular.woff2} +0 -0
  93. data/assets/fonts/notonaskh/bold-minimal.woff +0 -0
  94. data/assets/fonts/notonaskh/bold-minimal.woff2 +0 -0
  95. data/assets/fonts/notonaskh/bold.woff +0 -0
  96. data/assets/fonts/notonaskh/bold.woff2 +0 -0
  97. data/assets/fonts/notonaskh/regular-minimal.woff +0 -0
  98. data/assets/fonts/notonaskh/regular-minimal.woff2 +0 -0
  99. data/assets/fonts/notonaskh/regular.woff +0 -0
  100. data/assets/fonts/notonaskh/regular.woff2 +0 -0
  101. data/assets/fonts/{notosans-bold-subset.woff → notosans/notosans-bold-subset.woff} +0 -0
  102. data/assets/fonts/{notosans-bold-subset.woff2 → notosans/notosans-bold-subset.woff2} +0 -0
  103. data/assets/fonts/{notosans-bold.woff → notosans/notosans-bold.woff} +0 -0
  104. data/assets/fonts/{notosans-bold.woff2 → notosans/notosans-bold.woff2} +0 -0
  105. data/assets/fonts/{notosans-bolditalic-subset.woff → notosans/notosans-bolditalic-subset.woff} +0 -0
  106. data/assets/fonts/{notosans-bolditalic-subset.woff2 → notosans/notosans-bolditalic-subset.woff2} +0 -0
  107. data/assets/fonts/{notosans-bolditalic.woff → notosans/notosans-bolditalic.woff} +0 -0
  108. data/assets/fonts/{notosans-bolditalic.woff2 → notosans/notosans-bolditalic.woff2} +0 -0
  109. data/assets/fonts/{notosans-italic-subset.woff → notosans/notosans-italic-subset.woff} +0 -0
  110. data/assets/fonts/{notosans-italic-subset.woff2 → notosans/notosans-italic-subset.woff2} +0 -0
  111. data/assets/fonts/{notosans-italic.woff → notosans/notosans-italic.woff} +0 -0
  112. data/assets/fonts/{notosans-italic.woff2 → notosans/notosans-italic.woff2} +0 -0
  113. data/assets/fonts/{notosans-regular-subset.woff → notosans/notosans-regular-subset.woff} +0 -0
  114. data/assets/fonts/{notosans-regular-subset.woff2 → notosans/notosans-regular-subset.woff2} +0 -0
  115. data/assets/fonts/{notosans-regular.woff → notosans/notosans-regular.woff} +0 -0
  116. data/assets/fonts/{notosans-regular.woff2 → notosans/notosans-regular.woff2} +0 -0
  117. data/assets/fonts/notosansmono/notosansmono-semicondensed.woff +0 -0
  118. data/assets/fonts/notosansmono/notosansmono-semicondensed.woff2 +0 -0
  119. data/assets/fonts/notosansmono/notosansmono-semicondensedbold.woff +0 -0
  120. data/assets/fonts/notosansmono/notosansmono-semicondensedbold.woff2 +0 -0
  121. data/assets/images/icons.svg +24 -0
  122. data/assets/scripts/main.js +10 -3
  123. metadata +66 -33
  124. data/_data/lang.json +0 -730
  125. data/_data/techniques.yml +0 -180
  126. data/_data/wcag.yml +0 -125
  127. data/_includes/.DS_Store +0 -0
@@ -12,9 +12,24 @@
12
12
  }
13
13
  };
14
14
 
15
+ AblePlayer.prototype.updateCaptionsMenu = function (lang) {
16
+
17
+ // uncheck all previous menu items
18
+ this.captionsPopup.find('li').attr('aria-checked','false');
19
+ if (typeof lang === 'undefined') {
20
+ // check the last menu item (captions off)
21
+ this.captionsPopup.find('li').last().attr('aria-checked','true');
22
+ }
23
+ else {
24
+ // check the newly selected lang
25
+ this.captionsPopup.find('li[lang=' + lang + ']').attr('aria-checked','true');
26
+ }
27
+ };
28
+
15
29
  // Returns the function used when a caption is clicked in the captions menu.
16
30
  // Not called if user clicks "Captions off". Instead, that triggers getCaptionOffFunction()
17
31
  AblePlayer.prototype.getCaptionClickFunction = function (track) {
32
+
18
33
  var thisObj = this;
19
34
  return function () {
20
35
  thisObj.selectedCaptions = track;
@@ -58,6 +73,7 @@
58
73
  setTimeout(function() {
59
74
  thisObj.hidingPopup = false;
60
75
  }, 100);
76
+ thisObj.updateCaptionsMenu(thisObj.captionLang);
61
77
  thisObj.$ccButton.focus();
62
78
 
63
79
  // save preference to cookie
@@ -70,6 +86,7 @@
70
86
 
71
87
  // Returns the function used when the "Captions Off" button is clicked in the captions tooltip.
72
88
  AblePlayer.prototype.getCaptionOffFunction = function () {
89
+
73
90
  var thisObj = this;
74
91
  return function () {
75
92
  if (thisObj.player == 'youtube') {
@@ -86,6 +103,7 @@
86
103
  setTimeout(function() {
87
104
  thisObj.hidingPopup = false;
88
105
  }, 100);
106
+ thisObj.updateCaptionsMenu();
89
107
  thisObj.$ccButton.focus();
90
108
 
91
109
  // save preference to cookie
@@ -99,6 +117,7 @@
99
117
  };
100
118
 
101
119
  AblePlayer.prototype.showCaptions = function(now) {
120
+
102
121
  var c, thisCaption, captionText;
103
122
  var cues;
104
123
  if (this.selectedCaptions) {
@@ -78,6 +78,7 @@
78
78
  // add event listeners
79
79
  getClickFunction = function (time) {
80
80
  return function () {
81
+ thisObj.seekTrigger = 'chapter';
81
82
  $clickedItem = $(this).closest('li');
82
83
  $chaptersList = $(this).closest('ul').find('li');
83
84
  thisChapterIndex = $chaptersList.index($clickedItem);
@@ -239,4 +240,24 @@
239
240
  }
240
241
  };
241
242
 
243
+ AblePlayer.prototype.getChapterClickFunction = function (time) {
244
+
245
+ // Returns the function used when a chapter is clicked in the chapters menu.
246
+ var thisObj = this;
247
+ return function () {
248
+ thisObj.seekTrigger = 'chapter';
249
+ thisObj.seekTo(time);
250
+ // stopgap to prevent spacebar in Firefox from reopening popup
251
+ // immediately after closing it (used in handleChapters())
252
+ thisObj.hidingPopup = true;
253
+ thisObj.chaptersPopup.hide();
254
+ // Ensure stopgap gets cancelled if handleChapters() isn't called
255
+ // e.g., if user triggered button with Enter or mouse click, not spacebar
256
+ setTimeout(function() {
257
+ thisObj.hidingPopup = false;
258
+ }, 100);
259
+ thisObj.$chaptersButton.focus();
260
+ }
261
+ };
262
+
242
263
  })(jQuery);
@@ -1,6 +1,11 @@
1
1
  (function ($) {
2
2
  AblePlayer.prototype.seekTo = function (newTime) {
3
3
 
4
+ // define variables to be used for analytics
5
+ // e.g., to measure the extent to which users seek back and forward
6
+ this.seekFromTime = this.media.currentTime;
7
+ this.seekToTime = newTime;
8
+
4
9
  this.seeking = true;
5
10
  this.liveUpdatePending = true;
6
11
 
@@ -214,6 +219,9 @@
214
219
  };
215
220
 
216
221
  AblePlayer.prototype.playMedia = function () {
222
+
223
+ var thisObj = this;
224
+
217
225
  if (this.player === 'html5') {
218
226
  this.media.play(true);
219
227
  if (this.hasSignLanguage && this.signVideo) {
@@ -231,6 +239,52 @@
231
239
  this.stoppingYouTube = false;
232
240
  }
233
241
  this.startedPlaying = true;
242
+ if (this.hideControls) {
243
+ // wait briefly after playback begins, then hide controls
244
+ this.hidingControls = true;
245
+ this.hideControlsTimeout = window.setTimeout(function() {
246
+ thisObj.fadeControls('out');
247
+ thisObj.controlsHidden = true;
248
+ thisObj.hidingControls = false;
249
+ },2000);
250
+ }
251
+ };
252
+
253
+ AblePlayer.prototype.fadeControls = function(direction) {
254
+
255
+ // NOTE: This is a work in progress, and is not yet fully functional
256
+ // TODO: Use jQuery fadeIn() and fadeOut() to attain some sort of transition
257
+ // Currently just adds or removes able-offscreen class to visibly hide content
258
+ // without hiding it from screen reader users
259
+
260
+ // direction is either 'out' or 'in'
261
+
262
+ // One challenge:
263
+ // When controls fade out in other players (e.g., YouTube, Vimeo), the transition works well because
264
+ // their controls are an overlay on top of the video.
265
+ // Therefore, disappearing controls don't affect the size of the video container.
266
+ // Able Player's controls appear below the video, so if this.$playerDiv disappears,
267
+ // that results in a reduction in the height of the video container, which is a bit jarring
268
+ // Solution #1: Don't hide this.$playerDiv; instead hide the two containers nested inside it
269
+ if (direction == 'out') {
270
+ this.$controllerDiv.addClass('able-offscreen');
271
+ this.$statusBarDiv.addClass('able-offscreen');
272
+ // Removing content from $playerDiv leaves an empty controller bar in its place
273
+ // What to do with the empty space?
274
+ // For now, changing to a black background; will restore to original background on fade-in
275
+ this.playerBackground = this.$playerDiv.css('background-color');
276
+ this.$playerDiv.css('background-color','black');
277
+ }
278
+ else if (direction == 'in') {
279
+ this.$controllerDiv.removeClass('able-offscreen');
280
+ this.$statusBarDiv.removeClass('able-offscreen');
281
+ if (typeof this.playerBackground !== 'undefined') {
282
+ this.$playerDiv.css('background-color',this.playerBackground);
283
+ }
284
+ else {
285
+ this.$playerDiv.css('background-color','');
286
+ }
287
+ }
234
288
  };
235
289
 
236
290
  AblePlayer.prototype.refreshControls = function() {
@@ -238,8 +292,8 @@
238
292
  var thisObj, duration, elapsed, lastChapterIndex, displayElapsed,
239
293
  updateLive, textByState, timestamp, widthUsed,
240
294
  leftControls, rightControls, seekbarWidth, seekbarSpacer, captionsCount,
241
- buffered, newTop, svgLink, newSvgLink,
242
- statusBarHeight, speedHeight, statusBarWidthBreakpoint;
295
+ buffered, newTop, statusBarHeight, speedHeight, statusBarWidthBreakpoint,
296
+ newSvgData;
243
297
 
244
298
  thisObj = this;
245
299
  if (this.swappingSrc) {
@@ -340,7 +394,9 @@
340
394
  this.$playpauseButton.find('span.able-clipped').text(this.tt.play);
341
395
  }
342
396
  else if (this.iconType === 'svg') {
343
- // TODO: Add play/pause toggle for SVG
397
+ newSvgData = this.getSvgData('play');
398
+ this.$playpauseButton.find('svg').attr('viewBox',newSvgData[0]);
399
+ this.$playpauseButton.find('path').attr('d',newSvgData[1]);
344
400
  }
345
401
  else {
346
402
  this.$playpauseButton.find('img').attr('src',this.playButtonImg);
@@ -384,12 +440,9 @@
384
440
  this.$playpauseButton.find('span.able-clipped').text(this.tt.play);
385
441
  }
386
442
  else if (this.iconType === 'svg') {
387
- // Not currently working. SVG is a work in progress
388
- this.$playpauseButton.find('svg').removeClass('svg-pause').addClass('svg-play');
389
- svgLink = this.$playpauseButton.find('use').attr('xlink:href');
390
- newSvgLink = svgLink.replace('svg-pause','svg-play');
391
- this.$playpauseButton.find('use').attr(newSvgLink);
392
- this.$playpauseButton.find('span.able-clipped').text(this.tt.play);
443
+ newSvgData = this.getSvgData('play');
444
+ this.$playpauseButton.find('svg').attr('viewBox',newSvgData[0]);
445
+ this.$playpauseButton.find('path').attr('d',newSvgData[1]);
393
446
  }
394
447
  else {
395
448
  this.$playpauseButton.find('img').attr('src',this.playButtonImg);
@@ -403,12 +456,9 @@
403
456
  this.$playpauseButton.find('span.able-clipped').text(this.tt.pause);
404
457
  }
405
458
  else if (this.iconType === 'svg') {
406
- // Not currently working. SVG is a work in progress
407
- this.$playpauseButton.find('svg').removeClass('svg-play').addClass('svg-pause');
408
- svgLink = this.$playpauseButton.find('use').attr('xlink:href');
409
- newSvgLink = svgLink.replace('svg-play','svg-pause');
410
- this.$playpauseButton.find('use').attr(newSvgLink);
411
- this.$playpauseButton.find('span.able-clipped').text(this.tt.pause);
459
+ newSvgData = this.getSvgData('pause');
460
+ this.$playpauseButton.find('svg').attr('viewBox',newSvgData[0]);
461
+ this.$playpauseButton.find('path').attr('d',newSvgData[1]);
412
462
  }
413
463
  else {
414
464
  this.$playpauseButton.find('img').attr('src',this.pauseButtonImg);
@@ -517,7 +567,8 @@
517
567
  this.$ccButton.attr({
518
568
  'aria-label': this.tt.captions,
519
569
  'aria-haspopup': 'true',
520
- 'aria-controls': this.mediaId + '-captions-menu'
570
+ 'aria-controls': this.mediaId + '-captions-menu',
571
+ 'aria-expanded': 'false'
521
572
  });
522
573
  this.$ccButton.find('span.able-clipped').text(this.tt.captions);
523
574
  }
@@ -527,7 +578,8 @@
527
578
  this.$chaptersButton.attr({
528
579
  'aria-label': this.tt.chapters,
529
580
  'aria-haspopup': 'true',
530
- 'aria-controls': this.mediaId + '-chapters-menu'
581
+ 'aria-controls': this.mediaId + '-chapters-menu',
582
+ 'aria-expanded': 'false'
531
583
  });
532
584
  }
533
585
  if (this.$fullscreenButton) {
@@ -538,9 +590,9 @@
538
590
  this.$fullscreenButton.find('span.able-clipped').text(this.tt.enterFullScreen);
539
591
  }
540
592
  else if (this.iconType === 'svg') {
541
- // Not currently working. SVG is a work in progress.
542
- this.$fullscreenButton.find('svg').removeClass('icon-fullscreen-collapse').addClass('icon-fullscreen-expand');
543
- this.$fullscreenButton.find('span.able-clipped').text(this.tt.enterFullScreen);
593
+ newSvgData = this.getSvgData('fullscreen-expand');
594
+ this.$fullscreenButton.find('svg').attr('viewBox',newSvgData[0]);
595
+ this.$fullscreenButton.find('path').attr('d',newSvgData[1]);
544
596
  }
545
597
  else {
546
598
  this.$fullscreenButton.find('img').attr('src',this.fullscreenExpandButtonImg);
@@ -553,9 +605,9 @@
553
605
  this.$fullscreenButton.find('span.able-clipped').text(this.tt.exitFullScreen);
554
606
  }
555
607
  else if (this.iconType === 'svg') {
556
- // Not currently working. SVG is a work in progress.
557
- this.$fullscreenButton.find('svg').removeClass('icon-fullscreen-expand').addClass('icon-fullscreen-collapse');
558
- this.$fullscreenButton.find('span.able-clipped').text(this.tt.exitFullScreen);
608
+ newSvgData = this.getSvgData('fullscreen-collapse');
609
+ this.$fullscreenButton.find('svg').attr('viewBox',newSvgData[0]);
610
+ this.$fullscreenButton.find('path').attr('d',newSvgData[1]);
559
611
  }
560
612
  else {
561
613
  this.$fullscreenButton.find('img').attr('src',this.fullscreenCollapseButtonImg);
@@ -850,27 +902,23 @@
850
902
  this.refreshControls();
851
903
  }
852
904
  else {
853
-
854
905
  // there is more than one caption track.
855
906
  // clicking on a track is handled via caption.js > getCaptionClickFunction()
856
- if (this.captionsPopup.is(':visible')) {
907
+ if (this.captionsPopup && this.captionsPopup.is(':visible')) {
857
908
  this.captionsPopup.hide();
858
909
  this.hidingPopup = false;
859
- this.$ccButton.focus();
910
+ this.$ccButton.attr('aria-expanded','false').focus();
860
911
  }
861
912
  else {
862
913
  this.closePopups();
863
- this.captionsPopup.show();
864
- this.captionsPopup.css('top', this.$ccButton.position().top - this.captionsPopup.outerHeight());
865
- this.captionsPopup.css('left', this.$ccButton.position().left)
866
- // Focus on the checked button, if any buttons are checked
867
- // Otherwise, focus on the first button
868
- this.captionsPopup.find('li').removeClass('able-focus');
869
- if (this.captionsPopup.find('input:checked')) {
870
- this.captionsPopup.find('input:checked').focus().parent().addClass('able-focus');
871
- }
872
- else {
873
- this.captionsPopup.find('input').first().focus().parent().addClass('able-focus');
914
+ if (this.captionsPopup) {
915
+ this.captionsPopup.show();
916
+ this.$ccButton.attr('aria-expanded','true');
917
+ this.captionsPopup.css('top', this.$ccButton.position().top - this.captionsPopup.outerHeight());
918
+ this.captionsPopup.css('left', this.$ccButton.position().left)
919
+ // Place focus on the first button (even if another button is checked)
920
+ this.captionsPopup.find('li').removeClass('able-focus');
921
+ this.captionsPopup.find('li').first().focus().addClass('able-focus');
874
922
  }
875
923
  }
876
924
  }
@@ -886,21 +934,23 @@
886
934
  if (this.chaptersPopup.is(':visible')) {
887
935
  this.chaptersPopup.hide();
888
936
  this.hidingPopup = false;
889
- this.$chaptersButton.focus();
937
+ this.$chaptersButton.attr('aria-expanded','false').focus();
890
938
  }
891
939
  else {
892
940
  this.closePopups();
893
941
  this.chaptersPopup.show();
942
+ this.$chaptersButton.attr('aria-expanded','true');
894
943
  this.chaptersPopup.css('top', this.$chaptersButton.position().top - this.chaptersPopup.outerHeight());
895
944
  this.chaptersPopup.css('left', this.$chaptersButton.position().left)
896
- // Focus on the checked button, if any buttons are checked
897
- // Otherwise, focus on the first button
945
+
946
+ // Highlight the current chapter, if any chapters are checked
947
+ // Otherwise, place focus on the first chapter
898
948
  this.chaptersPopup.find('li').removeClass('able-focus');
899
- if (this.chaptersPopup.find('input:checked')) {
900
- this.chaptersPopup.find('input:checked').focus().parent().addClass('able-focus');
949
+ if (this.chaptersPopup.find('li[aria-checked="true"]').length) {
950
+ this.chaptersPopup.find('li[aria-checked="true"]').focus().addClass('able-focus');
901
951
  }
902
952
  else {
903
- this.chaptersPopup.find('input').first().focus().parent().addClass('able-focus');
953
+ this.chaptersPopup.find('li').first().addClass('able-focus').attr('aria-checked','true').focus();
904
954
  }
905
955
  }
906
956
  };
@@ -915,7 +965,6 @@
915
965
  };
916
966
 
917
967
  AblePlayer.prototype.handlePrefsClick = function(pref) {
918
-
919
968
  // NOTE: the prefs menu is positioned near the right edge of the player
920
969
  // This assumes the Prefs button is also positioned in that vicinity
921
970
  // (last or second-last button the right)
@@ -931,19 +980,22 @@
931
980
  if (this.prefsPopup.is(':visible')) {
932
981
  this.prefsPopup.hide();
933
982
  this.hidingPopup = false;
934
- this.$prefsButton.focus();
983
+ this.$prefsButton.attr('aria-expanded','false').focus();
984
+ // restore each menu item to original hidden state
985
+ this.prefsPopup.find('li').removeClass('able-focus').attr('tabindex','-1');
935
986
  }
936
987
  else {
937
988
  this.closePopups();
938
989
  this.prefsPopup.show();
990
+ this.$prefsButton.attr('aria-expanded','true');
939
991
  prefsButtonPosition = this.$prefsButton.position();
940
992
  prefsMenuRight = this.$ableDiv.width() - 5;
941
993
  prefsMenuLeft = prefsMenuRight - this.prefsPopup.width();
942
994
  this.prefsPopup.css('top', prefsButtonPosition.top - this.prefsPopup.outerHeight());
943
995
  this.prefsPopup.css('left', prefsMenuLeft);
944
- // remove prior focus and set focus on first item
945
- this.prefsPopup.find('li').removeClass('able-focus');
946
- this.prefsPopup.find('input').first().focus().parent().addClass('able-focus');
996
+ // remove prior focus and set focus on first item; also change tabindex from -1 to 0
997
+ this.prefsPopup.find('li').removeClass('able-focus').attr('tabindex','0');
998
+ this.prefsPopup.find('li').first().focus().addClass('able-focus');
947
999
  }
948
1000
  };
949
1001
 
@@ -958,6 +1010,7 @@
958
1010
  this.$transcriptButton.addClass('buttonOff').attr('aria-label',this.tt.showTranscript);
959
1011
  this.$transcriptButton.find('span.able-clipped').text(this.tt.showTranscript);
960
1012
  this.prefTranscript = 0;
1013
+ this.$transcriptButton.focus().addClass('able-focus');
961
1014
  }
962
1015
  else {
963
1016
  this.positionDraggableWindow('transcript');
@@ -975,6 +1028,7 @@
975
1028
  this.$signButton.addClass('buttonOff').attr('aria-label',this.tt.showSign);
976
1029
  this.$signButton.find('span.able-clipped').text(this.tt.showSign);
977
1030
  this.prefSign = 0;
1031
+ this.$signButton.focus().addClass('able-focus');
978
1032
  }
979
1033
  else {
980
1034
  this.positionDraggableWindow('sign');
@@ -1382,8 +1436,8 @@
1382
1436
  var max, $elements, z;
1383
1437
  max = 0;
1384
1438
 
1385
- // exclude the Able Player dialogs
1386
- $elements = $('body *').not('.able-modal-dialog,.able-modal-dialog *,.able-modal-overlay,.able-modal-overlay *');
1439
+ // exclude the Able Player dialogs and windows
1440
+ $elements = $('body *').not('.able-modal-dialog,.able-modal-dialog *,.able-modal-overlay,.able-modal-overlay *,.able-sign-window,.able-transcript-area');
1387
1441
 
1388
1442
  $elements.each(function(){
1389
1443
  z = $(this).css('z-index');
@@ -1401,22 +1455,48 @@
1401
1455
  // update z-index of 'transcript' or 'sign', relative to each other
1402
1456
  // direction is always 'up' (i.e., move window to top)
1403
1457
  // windows come to the top when the user clicks on them
1458
+ var defHighZ, defLowZ, highestZ, transcriptZ, signZ, newHighZ, newLowZ;
1459
+
1460
+ // set the default z-indexes, as defined in ableplayer.css
1461
+ defHighZ = 8000; // by default, assigned to the sign window
1462
+ defLowZ = 7000; // by default, assigned to the transcript area
1463
+ highestZ = this.getHighestZIndex(); // highest z-index on the page, excluding Able Player windows & modals
1404
1464
 
1405
- var transcriptZ, signZ, newHighZ, newLowZ;
1465
+ // NOTE: Although highestZ is collected here, it currently isn't used.
1466
+ // If something on the page has a higher z-index than the transcript or sign window, do we care?
1467
+ // Excluding it here assumes "No". Our immediate concern is with the relationship between our own components.
1468
+ // If we elevate our z-indexes so our content is on top, we run the risk of starting a z-index war.
1406
1469
 
1407
1470
  if (typeof this.$transcriptArea === 'undefined' || typeof this.$signWindow === 'undefined' ) {
1408
1471
  // at least one of the windows doesn't exist, so there's no conflict
1472
+ // since z-index may have been stored to a cookie on another page, need to restore default
1473
+ if (typeof this.$transcriptArea !== 'undefined') {
1474
+ transcriptZ = parseInt(this.$transcriptArea.css('z-index'));
1475
+ if (transcriptZ > defLowZ) {
1476
+ // restore to the default
1477
+ this.$transcriptArea.css('z-index',defLowZ);
1478
+ }
1479
+ }
1480
+ else if (typeof this.$signWindow !== 'undefined') {
1481
+ signZ = parseInt(this.$signWindow.css('z-index'));
1482
+ if (signZ > defHighZ) {
1483
+ // restore to the default
1484
+ this.$signWindow.css('z-index',defHighZ);
1485
+ }
1486
+ }
1409
1487
  return false;
1410
1488
  }
1411
1489
 
1490
+ // both windows exist
1491
+
1412
1492
  // get current values
1413
1493
  transcriptZ = parseInt(this.$transcriptArea.css('z-index'));
1414
1494
  signZ = parseInt(this.$signWindow.css('z-index'));
1415
1495
 
1416
1496
  if (transcriptZ === signZ) {
1417
- // the two windows are equal; move the target window the top
1418
- newHighZ = transcriptZ + 1000;
1419
- newLowZ = transcriptZ;
1497
+ // the two windows are equal; restore defaults (the target window will be on top)
1498
+ newHighZ = defHighZ;
1499
+ newLowZ = defLowZ;
1420
1500
  }
1421
1501
  else if (transcriptZ > signZ) {
1422
1502
  if (which === 'transcript') {
@@ -1431,6 +1511,7 @@
1431
1511
  }
1432
1512
  else { // signZ is greater
1433
1513
  if (which === 'sign') {
1514
+ // sign is already on top; nothing to do
1434
1515
  return false;
1435
1516
  }
1436
1517
  else {
@@ -1438,7 +1519,6 @@
1438
1519
  newLowZ = transcriptZ;
1439
1520
  }
1440
1521
  }
1441
-
1442
1522
  // now assign the new values
1443
1523
  if (which === 'transcript') {
1444
1524
  this.$transcriptArea.css('z-index',newHighZ);
@@ -1501,7 +1581,10 @@
1501
1581
  this.transcriptChapters = chapters;
1502
1582
  this.transcriptDescriptions = descriptions;
1503
1583
  this.updateChaptersList();
1504
- this.setupPopups('chapters');
1584
+ // the following was commented out in Oct/Nov 2018.
1585
+ // chapters popup is setup automatically when setupPopups() is called later with no param
1586
+ // not sure why it was included here.
1587
+ // this.setupPopups('chapters');
1505
1588
  }
1506
1589
  else if (source === 'transcript') {
1507
1590
  this.transcriptCaptions = captions;