Skip to content

Commit 0b248ac

Browse files
committed
Add support for data-seekbar-scope="chapter"
1 parent fc6e664 commit 0b248ac

15 files changed

Lines changed: 861 additions & 210 deletions

build/ableplayer.dist.js

Lines changed: 281 additions & 64 deletions
Large diffs are not rendered by default.

build/ableplayer.js

Lines changed: 281 additions & 64 deletions
Large diffs are not rendered by default.

build/ableplayer.min.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build/ableplayer.min.js

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

media/wwa_chapters_en.vtt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
WEBVTT
22
33
Chapter 1
4-
00:00:00.000 --> 00:00:30.000
4+
00:00:00.000 --> 00:00:39.000
55
Intro
66

77
Chapter 2

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ableplayer",
3-
"version": "2.3.24",
3+
"version": "2.3.25",
44
"description": "fully accessible HTML5 media player",
55
"homepage": "http://ableplayer.github.io/ableplayer",
66
"bugs": "https://github.com/ableplayer/ableplayer/issues",

scripts/ableplayer-base.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,25 @@
133133
this.useChaptersButton = false;
134134
}
135135

136+
// valid values are 'playlist' and 'chapter'; will also accept 'chapters'
137+
if ($(media).data('prevnext-unit') === 'chapter' || $(media).data('prevnext-unit') === 'chapters') {
138+
this.prevNextUnit = 'chapter';
139+
}
140+
else if ($(media).data('prevnext-unit') === 'playlist') {
141+
this.prevNextUnit = 'playlist';
142+
}
143+
else {
144+
this.prevNextUnit = false;
145+
}
146+
147+
// valid values are 'chapter' and 'video'; will also accept 'chapters'
148+
if ($(media).data('seekbar-scope') === 'chapter' || $(media).data('seekbar-scope') === 'chapters') {
149+
this.seekbarScope = 'chapter';
150+
}
151+
else {
152+
this.seekbarScope = 'video';
153+
}
154+
136155
if ($(media).data('youtube-id') !== undefined && $(media).data('youtube-id') !== "") {
137156
this.youTubeId = $(media).data('youtube-id');
138157
}

scripts/buildplayer.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,9 @@
252252
thisChapterIndex = $chaptersList.index($clickedItem);
253253
$chaptersList.removeClass('able-current-chapter').attr('aria-selected','');
254254
$clickedItem.addClass('able-current-chapter').attr('aria-selected','true');
255-
thisObj.currentChapter = thisObj.chapters[thisChapterIndex];
255+
console.log('onClick, updating chapter!');
256+
// Don't update this.currentChapter here; just seekTo chapter's start time; chapter will be updated via chapters.js > updateChapter()
257+
// thisObj.currentChapter = thisObj.chapters[thisChapterIndex];
256258
thisObj.seekTo(time);
257259
}
258260
};
@@ -903,7 +905,6 @@
903905
if (control === 'seek') {
904906
var sliderDiv = $('<div class="able-seekbar"></div>');
905907
controllerSpan.append(sliderDiv);
906-
907908
this.seekBar = new AccessibleSeekBar(sliderDiv, baseSliderWidth);
908909
}
909910
else if (control === 'pipe') {

scripts/chapters.js

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@
1212
}
1313
};
1414

15-
AblePlayer.prototype.updateChapter = function(now) {
15+
AblePlayer.prototype.updateChapter = function (now) {
1616

17-
// as time-synced chapters change during playback, update external container
17+
// as time-synced chapters change during playback, track changes in current chapter
1818

19-
if (typeof this.$chaptersDiv === 'undefined') {
19+
if (typeof this.chapters === 'undefined') {
2020
return;
2121
}
22+
2223
var chapters, i, thisChapterIndex, chapterLabel;
24+
2325
chapters = this.chapters;
2426
for (i in chapters) {
2527
if ((chapters[i].start <= now) && (chapters[i].end > now)) {
@@ -30,14 +32,81 @@
3032
if (typeof thisChapterIndex !== 'undefined') {
3133
if (this.currentChapter !== chapters[thisChapterIndex]) {
3234
// this is a new chapter
33-
this.$chaptersDiv.find('ul').find('li').removeClass('able-current-chapter').attr('aria-selected','');
34-
this.$chaptersDiv.find('ul').find('li').eq(thisChapterIndex)
35-
.addClass('able-current-chapter').attr('aria-selected','true');
3635
this.currentChapter = chapters[thisChapterIndex];
36+
if (this.useChapterTimes) {
37+
this.chapterDuration = this.getChapterDuration();
38+
this.seekIntervalCalculated = false; // will be recalculated in setSeekInterval()
39+
}
40+
if (typeof this.$chaptersDiv !== 'undefined') {
41+
// chapters are listed in an external container
42+
this.$chaptersDiv.find('ul').find('li').removeClass('able-current-chapter').attr('aria-selected','');
43+
this.$chaptersDiv.find('ul').find('li').eq(thisChapterIndex)
44+
.addClass('able-current-chapter').attr('aria-selected','true');
45+
}
46+
// announce new chapter via ARIA alert
3747
chapterLabel = this.tt.newChapter + ': ' + this.flattenCueForCaption(this.currentChapter);
3848
this.showAlert(chapterLabel,'screenreader');
3949
}
4050
}
4151
};
4252

53+
AblePlayer.prototype.getChapterDuration = function () {
54+
55+
// called if this.seekbarScope === 'chapter'
56+
// get duration of the current chapter
57+
58+
var videoDuration, lastChapterIndex, chapterEnd;
59+
60+
if (typeof this.currentChapter === 'undefined') {
61+
return duration;
62+
}
63+
videoDuration = this.getDuration();
64+
lastChapterIndex = this.chapters.length-1;
65+
if (this.chapters[lastChapterIndex] == this.currentChapter) {
66+
// this is the last chapter
67+
if (this.currentChapter.end !== videoDuration) {
68+
// chapter ends before or after video ends, adjust chapter end to match video end
69+
chapterEnd = videoDuration;
70+
this.currentChapter.end = videoDuration;
71+
}
72+
else {
73+
chapterEnd = this.currentChapter.end;
74+
}
75+
}
76+
else { // this is not the last chapter
77+
chapterEnd = this.currentChapter.end;
78+
}
79+
return chapterEnd - this.currentChapter.start;
80+
};
81+
82+
AblePlayer.prototype.getChapterElapsed = function () {
83+
84+
// called if this.seekbarScope === 'chapter'
85+
// get current elapsed time, relative to the current chapter duration
86+
if (typeof this.currentChapter === 'undefined') {
87+
return elapsed;
88+
}
89+
var videoDuration = this.getDuration();
90+
var videoElapsed = this.getElapsed();
91+
if (videoElapsed > this.currentChapter.start) {
92+
return videoElapsed - this.currentChapter.start;
93+
}
94+
else {
95+
return 0;
96+
}
97+
};
98+
99+
AblePlayer.prototype.convertChapterTimeToVideoTime = function (chapterTime) {
100+
101+
// chapterTime is the time within the current chapter
102+
// return the same time, relative to the entire video
103+
var newTime = this.currentChapter.start + chapterTime;
104+
if (newTime > this.currentChapter.end) {
105+
return this.currentChapter.end;
106+
}
107+
else {
108+
return newTime;
109+
}
110+
};
111+
43112
})(jQuery);

0 commit comments

Comments
 (0)