|
591 | 591 | this.loadCurrentPreferences(); |
592 | 592 | this.injectPlayerCode(); |
593 | 593 | this.setupTracks().then(function () { |
594 | | - thisObj.setupTooltips(); |
| 594 | + thisObj.setupPopupMenus(); |
595 | 595 | thisObj.initDescription(); |
596 | 596 | thisObj.initializing = false; |
597 | 597 | thisObj.initPlayer(); |
|
2250 | 2250 | }); |
2251 | 2251 | }; |
2252 | 2252 |
|
2253 | | - // Create tooltip with appropriate CSS styling and add to body. |
2254 | | - AblePlayer.prototype.createTooltip = function () { |
| 2253 | + // Create popup menu with appropriate CSS styling and add to body |
| 2254 | + // (e.g., for captions and chapters menus) |
| 2255 | + AblePlayer.prototype.createPopupMenu = function () { |
2255 | 2256 | var thisObj = this; |
2256 | 2257 | var tooltip = $('<div>'); |
2257 | | - tooltip.attr('role', 'tooltip'); |
| 2258 | + // tooltip.attr('role', 'tooltip'); // not really a tooltip |
2258 | 2259 | tooltip.addClass('able-tooltip'); |
2259 | 2260 |
|
2260 | | - // If tabbing off the tooltip, close it. |
| 2261 | + // If tabbing off the menu, close it. |
2261 | 2262 | tooltip.keydown(function (e) { |
2262 | 2263 | // Tab |
2263 | 2264 | if (e.which === 9) { |
2264 | 2265 | if (e.shiftKey) { |
2265 | 2266 | if (tooltip.find('button').first().is(':focus')) { |
2266 | | - thisObj.closeTooltips(); |
| 2267 | + thisObj.closePopupMenus(); |
2267 | 2268 | e.preventDefault(); |
2268 | 2269 | } |
2269 | 2270 | } |
2270 | 2271 | else { |
2271 | 2272 | if (tooltip.find('button').last().is(':focus')) { |
2272 | | - thisObj.closeTooltips(); |
| 2273 | + thisObj.closePopupMenus(); |
2273 | 2274 | e.preventDefault(); |
2274 | 2275 | } |
2275 | 2276 | } |
|
2281 | 2282 | return tooltip; |
2282 | 2283 | }; |
2283 | 2284 |
|
2284 | | - AblePlayer.prototype.closeTooltips = function () { |
2285 | | - if (this.chaptersTooltip && this.chaptersTooltip.is(':visible')) { |
2286 | | - this.chaptersTooltip.hide(); |
| 2285 | + AblePlayer.prototype.closePopupMenus = function () { |
| 2286 | + if (this.chaptersPopupMenu && this.chaptersPopupMenu.is(':visible')) { |
| 2287 | + this.chaptersPopupMenu.hide(); |
2287 | 2288 | this.$chaptersButton.focus(); |
2288 | 2289 | } |
2289 | | - if (this.captionsTooltip && this.captionsTooltip.is(':visible')) { |
2290 | | - this.captionsTooltip.hide(); |
| 2290 | + if (this.captionsPopupMenu && this.captionsPopupMenu.is(':visible')) { |
| 2291 | + this.captionsPopupMenu.hide(); |
2291 | 2292 | this.$ccButton.focus(); |
2292 | 2293 | } |
2293 | 2294 | }; |
2294 | 2295 |
|
2295 | | - // Create and fill in the tooltip forms for various controls. |
2296 | | - AblePlayer.prototype.setupTooltips = function () { |
2297 | | - this.setupCaptionsTooltip(); |
2298 | | - this.setupChaptersTooltip(); |
| 2296 | + // Create and fill in the popup menu forms for various controls. |
| 2297 | + AblePlayer.prototype.setupPopupMenus = function () { |
| 2298 | + this.setupCaptionsPopupMenu(); |
| 2299 | + this.setupChaptersPopupMenu(); |
2299 | 2300 | }; |
2300 | 2301 |
|
2301 | | - AblePlayer.prototype.setupCaptionsTooltip = function () { |
| 2302 | + AblePlayer.prototype.setupCaptionsPopupMenu = function () { |
2302 | 2303 | var thisObj = this; |
2303 | | - this.captionsTooltip = this.createTooltip(); |
| 2304 | + this.captionsPopupMenu = this.createPopupMenu(); |
2304 | 2305 |
|
2305 | 2306 | for (var ii in this.captions) { |
2306 | 2307 | var track = this.captions[ii]; |
|
2309 | 2310 | trackButton.attr('tabindex', 0); |
2310 | 2311 | trackButton.click(this.getCaptionClickFunction(track)); |
2311 | 2312 |
|
2312 | | - this.captionsTooltip.append(trackButton); |
2313 | | - this.captionsTooltip.append('<br>'); |
| 2313 | + this.captionsPopupMenu.append(trackButton); |
| 2314 | + this.captionsPopupMenu.append('<br>'); |
2314 | 2315 | } |
2315 | 2316 |
|
2316 | 2317 | // Captions Off option |
|
2319 | 2320 | offButton.html(this.tt.captionsOff); |
2320 | 2321 | offButton.click(this.getCaptionOffFunction()); |
2321 | 2322 |
|
2322 | | - this.captionsTooltip.append(offButton); |
| 2323 | + this.captionsPopupMenu.append(offButton); |
2323 | 2324 | }; |
2324 | 2325 |
|
2325 | | - AblePlayer.prototype.setupChaptersTooltip = function () { |
| 2326 | + AblePlayer.prototype.setupChaptersPopupMenu = function () { |
2326 | 2327 | var thisObj = this; |
2327 | | - this.chaptersTooltip = this.createTooltip(); |
| 2328 | + this.chaptersPopupMenu = this.createPopupMenu(); |
2328 | 2329 |
|
2329 | 2330 | for (var ii in this.chapters) { |
2330 | 2331 | var chapterButton = $('<button>'); |
|
2333 | 2334 | var getClickFunction = function (time) { |
2334 | 2335 | return function () { |
2335 | 2336 | thisObj.seekTo(time); |
2336 | | - thisObj.chaptersTooltip.hide(); |
| 2337 | + thisObj.chaptersPopupMenu.hide(); |
2337 | 2338 | thisObj.$chaptersButton.focus(); |
2338 | 2339 | } |
2339 | 2340 | } |
2340 | 2341 | chapterButton.click(getClickFunction(this.chapters[ii].start)); |
2341 | 2342 |
|
2342 | | - this.chaptersTooltip.append(chapterButton); |
2343 | | - this.chaptersTooltip.append('<br>'); |
| 2343 | + this.chaptersPopupMenu.append(chapterButton); |
| 2344 | + this.chaptersPopupMenu.append('<br>'); |
2344 | 2345 | } |
2345 | 2346 | }; |
2346 | 2347 |
|
|
2561 | 2562 | // some controls are aligned on the left, and others on the right |
2562 | 2563 |
|
2563 | 2564 | var useSpeedButtons, useFullScreen, |
2564 | | - i, j, controls, controllerSpan, control, |
| 2565 | + i, j, controls, controllerSpan, tooltipId, tooltipDiv, tooltipX, tooltipY, control, |
2565 | 2566 | buttonImg, buttonImgSrc, buttonTitle, newButton, iconClass, buttonIcon, |
2566 | 2567 | leftWidth, rightWidth, totalWidth, leftWidthStyle, rightWidthStyle, |
2567 | 2568 | controllerStyles, vidcapStyles; |
2568 | 2569 |
|
| 2570 | + var thisObj = this; |
| 2571 | + |
2569 | 2572 | var baseSliderWidth = 100; |
2570 | 2573 |
|
2571 | 2574 | // Initializes the layout into the this.controlLayout variable. |
2572 | 2575 | var controlLayout = this.calculateControlLayout(); |
2573 | 2576 |
|
2574 | 2577 | var sectionByOrder = {0: 'ul', 1:'ur', 2:'bl', 3:'br'}; |
2575 | | - // now step separately through left and right controls |
| 2578 | + |
| 2579 | + // add an empty div to serve as a tooltip |
| 2580 | + tooltipId = this.mediaId + '-tooltip'; |
| 2581 | + tooltipDiv = $('<div>',{ |
| 2582 | + 'id': tooltipId, |
| 2583 | + 'class': 'able-tooltip' |
| 2584 | + }); |
| 2585 | + this.$controllerDiv.append(tooltipDiv); |
| 2586 | + |
| 2587 | + // step separately through left and right controls |
2576 | 2588 | for (i = 0; i <= 3; i++) { |
2577 | 2589 | controls = controlLayout[sectionByOrder[i]]; |
2578 | 2590 | if ((i % 2) === 0) { |
|
2586 | 2598 | }); |
2587 | 2599 | } |
2588 | 2600 | this.$controllerDiv.append(controllerSpan); |
| 2601 | + |
2589 | 2602 | for (j=0; j<controls.length; j++) { |
2590 | 2603 | control = controls[j]; |
2591 | 2604 | if (control === 'seek') { |
|
2658 | 2671 | }); |
2659 | 2672 | newButton.append(buttonImg); |
2660 | 2673 | } |
2661 | | - // now add the visibly-hidden label for screen readers that don't support aria-label on the button |
| 2674 | + // add the visibly-hidden label for screen readers that don't support aria-label on the button |
2662 | 2675 | var buttonLabel = $('<span>',{ |
2663 | 2676 | 'class': 'able-clipped' |
2664 | 2677 | }).text(buttonTitle); |
2665 | 2678 | newButton.append(buttonLabel); |
| 2679 | + // add an event listener that displays a tooltip on mouseenter or focus |
| 2680 | + newButton.on('mouseenter focus',function(event) { |
| 2681 | + var label = $(this).attr('aria-label'); |
| 2682 | + // get position of this button |
| 2683 | + var position = $(this).position(); |
| 2684 | + var buttonHeight = $(this).height(); |
| 2685 | + var buttonWidth = $(this).width(); |
| 2686 | + var tooltipY = position.top - buttonHeight - 15; |
| 2687 | + var centerTooltip = true; |
| 2688 | + if ($(this).closest('span').hasClass('able-right-controls')) { |
| 2689 | + // this control is on the right side |
| 2690 | + if ($(this).is(':last-child')) { |
| 2691 | + // this is the last control on the right |
| 2692 | + // position tooltip using the "right" property |
| 2693 | + centerTooltip = false; |
| 2694 | + // var tooltipX = thisObj.playerWidth - position.left - buttonWidth; |
| 2695 | + var tooltipX = 0; |
| 2696 | + var tooltipStyle = { |
| 2697 | + left: '', |
| 2698 | + right: tooltipX + 'px', |
| 2699 | + top: tooltipY + 'px' |
| 2700 | + }; |
| 2701 | + } |
| 2702 | + } |
| 2703 | + else { |
| 2704 | + // this control is on the left side |
| 2705 | + if ($(this).is(':first-child')) { |
| 2706 | + // this is the first control on the left |
| 2707 | + centerTooltip = false; |
| 2708 | + var tooltipX = position.left; |
| 2709 | + var tooltipStyle = { |
| 2710 | + left: tooltipX + 'px', |
| 2711 | + right: '', |
| 2712 | + top: tooltipY + 'px' |
| 2713 | + }; |
| 2714 | + } |
| 2715 | + } |
| 2716 | + if (centerTooltip) { |
| 2717 | + // populate tooltip, then calculate its width before showing it |
| 2718 | + var tooltipWidth = $('#' + tooltipId).text(label).width(); |
| 2719 | + // center the tooltip horizontally over the button |
| 2720 | + var tooltipX = position.left - tooltipWidth/2; |
| 2721 | + var tooltipStyle = { |
| 2722 | + left: tooltipX + 'px', |
| 2723 | + right: '', |
| 2724 | + top: tooltipY + 'px' |
| 2725 | + }; |
| 2726 | + } |
| 2727 | + |
| 2728 | + $('#' + tooltipId).text(label).css(tooltipStyle).show(); |
| 2729 | + $(this).on('mouseleave blur',function() { |
| 2730 | + $('#' + tooltipId).text('').hide(); |
| 2731 | + }) |
| 2732 | + }); |
2666 | 2733 |
|
2667 | 2734 | if (control === 'captions') { |
2668 | 2735 | if (!this.prefCaptions || this.prefCaptions !== 1) { |
|
4688 | 4755 | this.refreshControls(); |
4689 | 4756 | } |
4690 | 4757 | else { |
4691 | | - if (this.captionsTooltip.is(':visible')) { |
4692 | | - this.captionsTooltip.hide(); |
| 4758 | + if (this.captionsPopupMenu.is(':visible')) { |
| 4759 | + this.captionsPopupMenu.hide(); |
4693 | 4760 | this.$ccButton.focus(); |
4694 | 4761 | } |
4695 | 4762 | else { |
4696 | | - this.closeTooltips(); |
4697 | | - this.captionsTooltip.show(); |
4698 | | - this.captionsTooltip.css('top', this.$ccButton.offset().top - this.captionsTooltip.outerHeight()); |
4699 | | - this.captionsTooltip.css('left', this.$ccButton.offset().left) |
| 4763 | + this.closePopupMenus(); |
| 4764 | + this.captionsPopupMenu.show(); |
| 4765 | + this.captionsPopupMenu.css('top', this.$ccButton.offset().top - this.captionsPopupMenu.outerHeight()); |
| 4766 | + this.captionsPopupMenu.css('left', this.$ccButton.offset().left) |
4700 | 4767 | // Focus the first chapter. |
4701 | | - this.captionsTooltip.children().first().focus(); |
| 4768 | + this.captionsPopupMenu.children().first().focus(); |
4702 | 4769 | } |
4703 | 4770 | } |
4704 | 4771 | }; |
4705 | 4772 |
|
4706 | 4773 | AblePlayer.prototype.handleChapters = function () { |
4707 | | - if (this.chaptersTooltip.is(':visible')) { |
4708 | | - this.chaptersTooltip.hide(); |
| 4774 | + if (this.chaptersPopupMenu.is(':visible')) { |
| 4775 | + this.chaptersPopupMenu.hide(); |
4709 | 4776 | this.$chaptersButton.focus(); |
4710 | 4777 | } |
4711 | 4778 | else { |
4712 | | - this.closeTooltips(); |
4713 | | - this.chaptersTooltip.show(); |
4714 | | - this.chaptersTooltip.css('top', this.$chaptersButton.offset().top - this.chaptersTooltip.outerHeight()); |
4715 | | - this.chaptersTooltip.css('left', this.$chaptersButton.offset().left) |
| 4779 | + this.closePopupMenus(); |
| 4780 | + this.chaptersPopupMenu.show(); |
| 4781 | + this.chaptersPopupMenu.css('top', this.$chaptersButton.offset().top - this.chaptersPopupMenu.outerHeight()); |
| 4782 | + this.chaptersPopupMenu.css('left', this.$chaptersButton.offset().left) |
4716 | 4783 | // Focus the first chapter. |
4717 | | - this.chaptersTooltip.children().first().focus(); |
| 4784 | + this.chaptersPopupMenu.children().first().focus(); |
4718 | 4785 | } |
4719 | 4786 | }; |
4720 | 4787 |
|
|
4946 | 5013 | thisObj.currentDescription = -1; |
4947 | 5014 | } |
4948 | 5015 | } |
4949 | | - thisObj.captionsTooltip.hide(); |
| 5016 | + thisObj.captionsPopupMenu.hide(); |
4950 | 5017 | thisObj.$ccButton.focus(); |
4951 | 5018 | thisObj.refreshControls(); |
4952 | 5019 | thisObj.updateCaption(); |
|
4960 | 5027 | return function () { |
4961 | 5028 | thisObj.captionsOn = false; |
4962 | 5029 | thisObj.currentCaption = -1; |
4963 | | - thisObj.captionsTooltip.hide(); |
| 5030 | + thisObj.captionsPopupMenu.hide(); |
4964 | 5031 | thisObj.$ccButton.focus(); |
4965 | 5032 | thisObj.refreshControls(); |
4966 | 5033 | thisObj.updateCaption(); |
|
5795 | 5862 | } |
5796 | 5863 |
|
5797 | 5864 | if (which === 27) { // Escape - TODO: Not listed in help file, should it be? |
5798 | | - this.closeTooltips(); |
| 5865 | + this.closePopupMenus(); |
5799 | 5866 | } |
5800 | 5867 | else if (which === 32) { // spacebar = play/pause |
5801 | 5868 | if (!($('.able-controller button').is(':focus'))) { |
|
0 commit comments