Merge pull request #854 from edx/jmclaus/bugfix_tabbing_video_speed_control
Speed button know behaves like the volume button when tabbing forward or...
This commit is contained in:
@@ -82,6 +82,38 @@
|
||||
$('.speeds').mouseenter().click();
|
||||
expect($('.speeds')).not.toHaveClass('open');
|
||||
});
|
||||
// Tabbing depends on the following order:
|
||||
// 1. Play anchor
|
||||
// 2. Speed anchor
|
||||
// 3. A number of speed entry anchors
|
||||
// 4. Volume anchor
|
||||
// If an other focusable element is inserted or if the order is changed, things will
|
||||
// malfunction as a flag, state.previousFocus, is set in the 1,3,4 elements and is
|
||||
// used to determine the behavior of foucus() and blur() for the speed anchor.
|
||||
it('checks for a certain order in focusable elements in video controls', function() {
|
||||
var playIndex, speedIndex, firstSpeedEntry, lastSpeedEntry, volumeIndex, foundFirst = false;
|
||||
$('.video-controls').find('a, :focusable').each(function(index) {
|
||||
if ($(this).hasClass('video_control')) {
|
||||
playIndex = index;
|
||||
}
|
||||
else if ($(this).parent().hasClass('speeds')) {
|
||||
speedIndex = index;
|
||||
}
|
||||
else if ($(this).hasClass('speed_link')) {
|
||||
if (!foundFirst) {
|
||||
firstSpeedEntry = index;
|
||||
foundFirst = true;
|
||||
}
|
||||
lastSpeedEntry = index;
|
||||
}
|
||||
else if ($(this).parent().hasClass('volume')) {
|
||||
volumeIndex = index;
|
||||
}
|
||||
});
|
||||
expect(playIndex+1).toEqual(speedIndex);
|
||||
expect(speedIndex+1).toEqual(firstSpeedEntry);
|
||||
expect(lastSpeedEntry+1).toEqual(volumeIndex);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -77,6 +77,11 @@ function () {
|
||||
state.el.on('mousemove', state.videoControl.showControls);
|
||||
state.el.on('keydown', state.videoControl.showControls);
|
||||
}
|
||||
// The state.previousFocus is used in video_speed_control to track
|
||||
// the element that had the focus before it.
|
||||
state.videoControl.playPauseEl.on('blur', function () {
|
||||
state.previousFocus = 'playPause';
|
||||
});
|
||||
}
|
||||
|
||||
// ***************************************************************
|
||||
|
||||
@@ -125,6 +125,9 @@ function () {
|
||||
// We store the fact that previous element that lost focus was
|
||||
// the volume clontrol.
|
||||
state.volumeBlur = true;
|
||||
// The following field is used in video_speed_control to track
|
||||
// the element that had the focus before it.
|
||||
state.previousFocus = 'volume';
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -154,68 +154,92 @@ function () {
|
||||
});
|
||||
|
||||
// ******************************
|
||||
// Attach 'focus', and 'blur' events to the speed button which
|
||||
// The tabbing will cycle through the elements in the following
|
||||
// order:
|
||||
// 1. Play control
|
||||
// 2. Speed control
|
||||
// 3. Fastest speed called firstSpeed
|
||||
// 4. Intermediary speed called otherSpeed
|
||||
// 5. Slowest speed called lastSpeed
|
||||
// 6. Volume control
|
||||
// This field will keep track of where the focus is coming from.
|
||||
state.previousFocus = '';
|
||||
|
||||
// ******************************
|
||||
// Attach 'focus', and 'blur' events to the speed control which
|
||||
// either brings up the speed dialog with individual speed entries,
|
||||
// or closes it.
|
||||
state.videoSpeedControl.el.children('a')
|
||||
.on('focus', function () {
|
||||
// If the focus is comming from the first speed entry, this
|
||||
// means we are tabbing backwards. In this case we have to
|
||||
// hide the speed entries which will allow us to change the
|
||||
// focus further backwards.
|
||||
if (state.firstSpeedBlur === true) {
|
||||
state.videoSpeedControl.el.removeClass('open');
|
||||
|
||||
state.firstSpeedBlur = false;
|
||||
}
|
||||
|
||||
// If the focus is comming from some other element, show
|
||||
// the drop down with the speed entries.
|
||||
else {
|
||||
state.videoSpeedControl.el.addClass('open');
|
||||
// If the focus is coming from the first speed entry
|
||||
// (tabbing backwards) or last speed entry (tabbing forward)
|
||||
// hide the speed entries dialog.
|
||||
if (state.previousFocus === 'firstSpeed' ||
|
||||
state.previousFocus === 'lastSpeed') {
|
||||
state.videoSpeedControl.el.removeClass('open');
|
||||
}
|
||||
})
|
||||
.on('blur', function () {
|
||||
// When the focus leaves this element, if the speed entries
|
||||
// dialog is shown (tabbing forwards), then we will set
|
||||
// focus to the first speed entry.
|
||||
//
|
||||
// If the selector does not select anything, then this
|
||||
// means that the speed entries dialog is closed, and we
|
||||
// are tabbing backwads. The browser will select the
|
||||
// previous element to tab to by itself.
|
||||
state.videoSpeedControl.videoSpeedsEl
|
||||
// When the focus leaves this element, the speed entries
|
||||
// dialog will be shown.
|
||||
|
||||
// If we are tabbing forward (previous focus is play
|
||||
// control), we open the dialog and set focus on the first
|
||||
// speed entry.
|
||||
if (state.previousFocus === 'playPause') {
|
||||
state.videoSpeedControl.el.addClass('open');
|
||||
state.videoSpeedControl.videoSpeedsEl
|
||||
.find('a.speed_link:first')
|
||||
.focus();
|
||||
}
|
||||
|
||||
// If we are tabbing backwards (previous focus is volume
|
||||
// control), we open the dialog and set focus on the
|
||||
// last speed entry.
|
||||
if (state.previousFocus === 'volume') {
|
||||
state.videoSpeedControl.el.addClass('open');
|
||||
state.videoSpeedControl.videoSpeedsEl
|
||||
.find('a.speed_link:last')
|
||||
.focus();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
// ******************************
|
||||
// Attach 'focus', and 'blur' events to elements which represent
|
||||
// individual speed entries.
|
||||
// Attach 'blur' event to elements which represent individual speed
|
||||
// entries and use it to track the origin of the focus.
|
||||
speedLinks = state.videoSpeedControl.videoSpeedsEl
|
||||
.find('a.speed_link');
|
||||
|
||||
speedLinks.last().on('blur', function () {
|
||||
// If we have reached the last speed entry, and the focus
|
||||
// changes to the next element, we need to hide the speeds
|
||||
// control drop-down.
|
||||
state.videoSpeedControl.el.removeClass('open');
|
||||
});
|
||||
speedLinks.first().on('blur', function () {
|
||||
// This flag will indicate that the focus to the next
|
||||
// element that will receive it is comming from the first
|
||||
// speed entry.
|
||||
//
|
||||
// This flag will be used to correctly handle scenario of
|
||||
// tabbing backwards.
|
||||
state.firstSpeedBlur = true;
|
||||
// The previous focus is a speed entry (we are tabbing
|
||||
// backwards), the dialog will close, set focus on the speed
|
||||
// control and track the focus on first speed.
|
||||
if (state.previousFocus === 'otherSpeed') {
|
||||
state.previousFocus = 'firstSpeed';
|
||||
state.videoSpeedControl.el.children('a').focus();
|
||||
}
|
||||
});
|
||||
speedLinks.on('focus', function () {
|
||||
// Clear the flag which is only set when we are un-focusing
|
||||
// (the blur event) from the first speed entry.
|
||||
state.firstSpeedBlur = false;
|
||||
|
||||
// Track the focus on intermediary speeds.
|
||||
speedLinks
|
||||
.filter(function (index) {
|
||||
return index === 1 || index === 2
|
||||
})
|
||||
.on('blur', function () {
|
||||
state.previousFocus = 'otherSpeed';
|
||||
});
|
||||
|
||||
speedLinks.last().on('blur', function () {
|
||||
// The previous focus is a speed entry (we are tabbing forward),
|
||||
// the dialog will close, set focus on the speed control and
|
||||
// track the focus on last speed.
|
||||
if (state.previousFocus === 'otherSpeed') {
|
||||
state.previousFocus = 'lastSpeed';
|
||||
state.videoSpeedControl.el.children('a').focus();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user