This repository has been archived by the owner on Jan 11, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
/
EasyCaptions.js
221 lines (157 loc) · 7.33 KB
/
EasyCaptions.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/*--------------------------------------------------------------------
EasyCaptions v0.1.20111123
https://github.com/pipwerks/EasyCaptions
Copyright (c) Philip Hutchison
MIT-style license: http://pipwerks.mit-license.org/
--------------------------------------------------------------------*/
var EasyCaptions = function (options){
/* Declare all variables */
//Strings stored as vars for better minification/compression
var UNDEFINED = "undefined",
STRING = "string",
FUNCTION = "function",
SPACE = " ",
MAYBE = "maybe",
PROBABLY = "probably",
TYPE = "type",
SPAN = "span",
DATABEGIN = "data-begin",
DATAEND = "data-end",
TRUE = true,
FALSE = false,
$id = function (id){ return document.getElementById(id); },
enable_transcript = (typeof options.enableTranscript !== UNDEFINED) ? options.enableTranscript : TRUE,
enable_captions = (typeof options.enableCaptions !== UNDEFINED) ? options.enableCaptions : TRUE,
//Determine if HTML element was passed as argument or element's ID (string)
//If string, get it using $id (internal shortcut for document.getElementById)
transcript_element = (typeof options.transcriptElementID === STRING) ? $id(options.transcriptElementID) : options.transcriptElementID || FALSE,
video_element = (typeof options.videoElementID === STRING) ? $id(options.videoElementID) : options.videoElementID || FALSE,
//The class to append to the transcript text container.
//If no custom class provided by user, use default
transcript_enabled_class = options.transcriptEnabledClass || "EasyCaptions-enabled",
//The ID to append to the generated caption area. If no custom ID provided by user, use default
caption_id = options.captionID || "EasyCaptions-caption",
caption_array = [],
caption_element,
html5_supported,
//Internal functions
isHtml5VideoSupported = function (){
var isSupported = FALSE,
video = video_element || FALSE,
video_element_type = (video && video.getAttribute(TYPE) !== UNDEFINED) ? video.getAttribute(TYPE) : FALSE,
canplay = (typeof video.canPlayType !== UNDEFINED);
if(!video){ return FALSE; }
if(video_element_type){
canplay = video.canPlayType(video_element_type);
isSupported = video_element_type && (canplay === MAYBE || canplay === PROBABLY);
} else {
if(canplay){
var src = video.getElementsByTagName("source");
for (var i=0; i < src.length; i++){
canplay = video.canPlayType(src[i].getAttribute(TYPE));
if(canplay === MAYBE || canplay === PROBABLY){
isSupported = TRUE;
break;
}
}
}
}
return isSupported;
},
//Copies text stored in caption array
updateCaption = function (timecode){
if(typeof caption_array[timecode] !== UNDEFINED){
caption_element.innerHTML = caption_array[timecode];
}
},
//For HTML5 captions
timeupdateHandler = function () { updateCaption(parseInt(this.currentTime, 10)); },
//Create page element for displaying caption text
createCaptionField = function (video_element, caption_id){
var caption = $id(caption_id);
if(!caption && typeof video_element !== UNDEFINED){
caption = document.createElement("div");
caption.id = caption_id;
caption.innerHTML = SPACE;
video_element.parentNode.appendChild(caption);
}
return caption;
},
//Get all caption text, store in array
getSpans = function (transcript_el){
if(!transcript_el){ return FALSE; }
var spans = transcript_el.getElementsByTagName(SPAN),
captionArray = [];
for(var i=0, count = spans.length; i < count; i++){
var beginNum = spans[i].getAttribute(DATABEGIN);
var endNum = spans[i].getAttribute(DATAEND);
captionArray[beginNum] = spans[i].innerHTML;
captionArray[endNum] = SPACE;
}
return captionArray;
},
//Provide ability to create interactive transcripts
enableTranscript = function (custom_handler, alt_video_element){
//Ensure one of the approaches will work before continuing
if(!html5_supported && typeof custom_handler !== FUNCTION){ return FALSE; }
//Append classname to transcript text container.
//This allows developers to turn on CSS styling for hover state
if(transcript_element.className.indexOf(transcript_enabled_class) === -1){
transcript_element.className = transcript_element.className + " " +transcript_enabled_class;
}
//Using event delegation to make *transcript_element* clickable instead of individual spans
transcript_element.onclick = function (e){
var event = e || window.event,
target = event.target || event.srcElement,
position;
if (target.nodeName.toLowerCase() === SPAN) {
position = target.getAttribute(DATABEGIN);
if(typeof position === UNDEFINED){ return FALSE; }
//Browser supports HTML5 video. Use HTML5 currentTime method.
if(html5_supported && video_element){ video_element.currentTime = position; }
//Invoke user's specified video handler.
if(!html5_supported && alt_video_element && custom_handler){ custom_handler(alt_video_element, position); }
}
};
},
enableCaptions = function (custom_handler, alt_video_element){
//Ensure one of the approaches will work before continuing
if(!html5_supported && typeof custom_handler !== FUNCTION){ return FALSE; }
//Get all caption_array text, store in array
if(caption_array.length === 0){ caption_array = getSpans(transcript_element); }
//Create page element for displaying caption text
if(!caption_element){
var target = (!html5_supported && alt_video_element) ? alt_video_element : video_element;
caption_element = createCaptionField(target, caption_id);
}
//Set up HTML5 listener
if(html5_supported){ video_element.addEventListener("timeupdate", timeupdateHandler, FALSE); }
//Invoke user's specified video handler.
if(!html5_supported && alt_video_element && custom_handler){ custom_handler(alt_video_element, updateCaption); }
},
enableFallback = function (params){
var caption_handler = (typeof params.captionHandler === FUNCTION) ? params.captionHandler : FALSE,
transcript_handler = (typeof params.transcriptHandler === FUNCTION) ? params.transcriptHandler : FALSE,
//Check to see if ID or DOM element was passed as argument
alt_video_element = (typeof params.elementID === UNDEFINED) ? FALSE : (typeof params.elementID === STRING) ? $id(params.elementID) : params.elementID;
//Ensure we have something to work with before continuing
if(!alt_video_element || (!caption_handler && !transcript_handler)){ return FALSE; }
if(caption_handler){ enableCaptions(caption_handler, alt_video_element); }
if(transcript_handler){ enableTranscript(transcript_handler, alt_video_element); }
};
//Check for user-defined settings. Set defaults where appropriate.
//Detect if HTML5 video is supported
html5_supported = isHtml5VideoSupported();
//Enable transcript
if(enable_transcript){ enableTranscript(); }
//Enable captions
if(enable_captions){ enableCaptions(); }
/* Public API */
this.video = video_element;
this.transcript_element = transcript_element;
this.caption_element = caption_element;
this.updateCaption = updateCaption;
this.html5_supported = html5_supported;
this.addFallback = enableFallback;
return this;
};