@@ -53,6 +53,7 @@ function ablePlayerSetupWindow() {
5353 * you are running outside the browser (for example, SSR).
5454 *
5555 * @param object media jQuery selector or element identifying the media.
56+ * @param object options Optional configuration options for the player.
5657 */
5758 function AblePlayer ( media ) {
5859
@@ -82,17 +83,19 @@ function ablePlayerSetupWindow() {
8283 this . okToPlay = false ;
8384 }
8485
86+ let data = media [ 0 ] . dataset ;
87+
8588 // loop (Boolean; if present always resolves to true, regardless of value)
86- this . loop = ( $ ( media ) . attr ( ' loop' ) !== undefined ) ? true : false ;
89+ this . loop = ( data . loop !== undefined ) ? true : false ;
8790
8891 // playsinline (Boolean; if present always resolves to true, regardless of value)
8992 this . playsInline = ( $ ( media ) . attr ( 'playsinline' ) !== undefined ) ? '1' : '0' ;
9093
9194 // poster (Boolean, indicating whether media element has a poster attribute)
92- this . hasPoster = ( $ ( media ) . attr ( 'poster' ) || $ ( media ) . data ( ' poster' ) ) ? true : false ;
95+ this . hasPoster = ( $ ( media ) . attr ( 'poster' ) || data . poster ) ? true : false ;
9396
94- this . audioPoster = $ ( media ) . data ( ' poster' ) ;
95- this . audioPosterAlt = $ ( media ) . data ( 'poster-alt' ) ;
97+ this . audioPoster = data . poster ;
98+ this . audioPosterAlt = data . posterAlt ;
9699
97100 // get height and width attributes, if present
98101 // and add them to variables
@@ -101,18 +104,18 @@ function ablePlayerSetupWindow() {
101104 this . height = $ ( media ) . attr ( 'height' ) ?? 0 ;
102105
103106 // start-time
104- var startTime = $ ( media ) . data ( 'start-time' ) ;
107+ var startTime = data . startTime ;
105108 var isNumeric = ( typeof startTime === 'number' || ( typeof startTime === 'string' && startTime . trim ( ) !== '' && ! isNaN ( startTime ) && isFinite ( Number ( startTime ) ) ) ) ? true : false ;
106109 this . startTime = ( startTime !== undefined && isNumeric ) ? startTime : 0 ;
107110
108111 // debug
109- this . debug = ( $ ( media ) . data ( ' debug' ) !== undefined && $ ( media ) . data ( ' debug' ) !== false ) ? true : false ;
112+ this . debug = ( data . debug !== undefined && data . debug !== false ) ? true : false ;
110113
111114 // Volume
112115 // Range is 0 to 10. Best not to crank it to avoid overpowering screen readers
113116 this . defaultVolume = 7 ;
114- if ( $ ( media ) . data ( ' volume' ) !== undefined && $ ( media ) . data ( ' volume' ) !== "" ) {
115- var volume = $ ( media ) . data ( ' volume' ) ;
117+ if ( data . volume !== undefined && data . volume !== "" ) {
118+ var volume = data . volume ;
116119 if ( volume >= 0 && volume <= 10 ) {
117120 this . defaultVolume = volume ;
118121 }
@@ -124,7 +127,7 @@ function ablePlayerSetupWindow() {
124127 // However, in some applications it might be undesirable to show buttons
125128 // (e.g., if chapters or transcripts are provided in an external container)
126129
127- if ( $ ( media ) . data ( 'use-chapters-button' ) !== undefined && $ ( media ) . data ( 'use-chapters-button' ) === false ) {
130+ if ( data . useChaptersButton !== undefined && data . useChaptersButton === false ) {
128131 this . useChaptersButton = false ;
129132 } else {
130133 this . useChaptersButton = true ;
@@ -136,9 +139,9 @@ function ablePlayerSetupWindow() {
136139 // set to "true" to write description text to a div
137140 // This variable does *not* control the method by which description is read.
138141 // For that, see below (this.descMethod)
139- if ( $ ( media ) . data ( 'descriptions-audible' ) !== undefined && $ ( media ) . data ( 'descriptions-audible' ) === false ) {
142+ if ( data . descriptionsAudible !== undefined && data . descriptionsAudible === false ) {
140143 this . readDescriptionsAloud = false ;
141- } else if ( $ ( media ) . data ( 'description-audible' ) !== undefined && $ ( media ) . data ( 'description-audible' ) === false ) {
144+ } else if ( data . descriptionAudible !== undefined && data . descriptionAudible === false ) {
142145 // support both singular and plural spelling of attribute
143146 this . readDescriptionsAloud = false ;
144147 } else {
@@ -155,29 +158,29 @@ function ablePlayerSetupWindow() {
155158 // 'screenreader' - text-based audio description is always handled by screen readers
156159 // The latter may be preferable by owners of websites in languages that are not well supported
157160 // by the Web Speech API
158- this . descReader = ( $ ( media ) . data ( 'desc-reader' ) == 'screenreader' ) ? 'screenreader' : 'browser' ;
161+ this . descReader = ( data . descReader == 'screenreader' ) ? 'screenreader' : 'browser' ;
159162
160163 // Default state of captions and descriptions
161164 // This setting is overridden by user preferences, if they exist
162165 // values for data-state-captions and data-state-descriptions are 'on' or 'off'
163- this . defaultStateCaptions = ( $ ( media ) . data ( 'state-captions' ) == 'off' ) ? 0 : 1 ;
164- this . defaultStateDescriptions = ( $ ( media ) . data ( 'state-descriptions' ) == 'on' ) ? 1 : 0 ;
166+ this . defaultStateCaptions = ( data . stateCaptions == 'off' ) ? 0 : 1 ;
167+ this . defaultStateDescriptions = ( data . stateDescriptions == 'on' ) ? 1 : 0 ;
165168
166169 // Default setting for prefDescPause
167170 // Extended description (i.e., pausing during description) is on by default
168171 // but this settings give website owners control over that
169172 // since they know the nature of their videos, and whether pausing is necessary
170173 // This setting is overridden by user preferences, if they exist
171- this . defaultDescPause = ( $ ( media ) . data ( 'desc-pause-default' ) == 'off' ) ? 0 : 1 ;
174+ this . defaultDescPause = ( data . descPauseDefault == 'off' ) ? 0 : 1 ;
172175
173176 // Headings
174177 // By default, an off-screen heading is automatically added to the top of the media player
175178 // It is intelligently assigned a heading level based on context, via misc.js > getNextHeadingLevel()
176179 // Authors can override this behavior by manually assigning a heading level using data-heading-level
177180 // Accepted values are 1-6, or 0 which indicates "no heading"
178181 // (i.e., author has already hard-coded a heading before the media player; Able Player doesn't need to do this)
179- if ( $ ( media ) . data ( 'heading-level' ) !== undefined && $ ( media ) . data ( 'heading-level' ) !== "" ) {
180- var headingLevel = $ ( media ) . data ( 'heading-level' ) ;
182+ if ( data . headingLevel !== undefined && data . headingLevel !== "" ) {
183+ var headingLevel = data . headingLevel ;
181184 if ( / ^ [ 0 - 6 ] * $ / . test ( headingLevel ) ) { // must be a valid HTML heading level 1-6; or 0
182185 this . playerHeadingLevel = headingLevel ;
183186 }
@@ -190,18 +193,18 @@ function ablePlayerSetupWindow() {
190193 // 2. "external" - Automatically generated, written to an external div (requires data-transcript-div & a valid target element)
191194 // 3. "popup" - Automatically generated, written to a draggable, resizable popup window that can be toggled on/off with a button
192195 // If data-include-transcript="false", there is no "popup" transcript
193- var transcriptDivLocation = $ ( media ) . data ( 'transcript-div' ) ;
196+ var transcriptDivLocation = data . transcriptDiv ;
194197 if ( transcriptDivLocation !== undefined && transcriptDivLocation !== "" && null !== document . getElementById ( transcriptDivLocation ) ) {
195198 this . transcriptDivLocation = transcriptDivLocation ;
196199 } else {
197200 this . transcriptDivLocation = null ;
198201 }
199- var includeTranscript = $ ( media ) . data ( 'include-transcript' ) ;
202+ var includeTranscript = data . includeTranscript ;
200203 this . hideTranscriptButton = ( includeTranscript !== undefined && includeTranscript === false ) ? true : false ;
201204
202205 this . transcriptType = null ;
203- if ( $ ( media ) . data ( 'transcript-src' ) !== undefined ) {
204- this . transcriptSrc = $ ( media ) . data ( 'transcript-src' ) ;
206+ if ( data . transcriptSrc !== undefined ) {
207+ this . transcriptSrc = data . transcriptSrc ;
205208 if ( this . transcriptSrcHasRequiredParts ( ) ) {
206209 this . transcriptType = 'manual' ;
207210 } else {
@@ -215,20 +218,20 @@ function ablePlayerSetupWindow() {
215218 // In "Lyrics Mode", line breaks in WebVTT caption files are supported in the transcript
216219 // If false (default), line breaks are are removed from transcripts for a more seamless reading experience
217220 // If true, line breaks are preserved, so content can be presented karaoke-style, or as lines in a poem
218- this . lyricsMode = ( $ ( media ) . data ( 'lyrics-mode' ) !== undefined && $ ( media ) . data ( 'lyrics-mode' ) !== false ) ? true : false ;
221+ this . lyricsMode = ( data . lyricsMode !== undefined && data . lyricsMode !== false ) ? true : false ;
219222
220223 // in Strict Mode, parentheses and brackets do not get marked in bold in transcripts, and line breaks are not injected.
221224 // In Able Player 5.1, defaults to false.
222- this . strictMode = ( $ ( media ) . data ( 'strict-mode' ) === undefined && $ ( media ) . data ( 'strict-mode' ) !== true ) ? false : true ;
225+ this . strictMode = ( data . strictMode === undefined && data . strictMode !== true ) ? false : true ;
223226
224227 // Set Transcript Title if defined explicitly. See transcript.js.
225- if ( $ ( media ) . data ( 'transcript-title' ) !== undefined && $ ( media ) . data ( 'transcript-title' ) !== "" ) {
226- this . transcriptTitle = $ ( media ) . data ( 'transcript-title' ) ;
228+ if ( data . transcriptTitle !== undefined && data . transcriptTitle !== "" ) {
229+ this . transcriptTitle = data . transcriptTitle ;
227230 }
228231
229232 // Sign Language
230233 // sign language can be a modal (default) or assigned to a div on the page.
231- var signDivLocation = $ ( media ) . data ( 'sign-div' ) ;
234+ var signDivLocation = data . signDiv ;
232235 if ( signDivLocation !== undefined && signDivLocation !== "" && null !== document . getElementById ( signDivLocation ) ) {
233236 this . $signDivLocation = $ ( '#' + signDivLocation ) ;
234237 } else {
@@ -239,34 +242,34 @@ function ablePlayerSetupWindow() {
239242 // data-captions-position can be used to set the default captions position
240243 // this is only the default, and can be overridden by user preferences
241244 // valid values of data-captions-position are 'below' and 'overlay'
242- this . defaultCaptionsPosition = ( $ ( media ) . data ( 'captions-position' ) === 'overlay' ) ? 'overlay' : 'below' ;
245+ this . defaultCaptionsPosition = ( data . captionsPosition === 'overlay' ) ? 'overlay' : 'below' ;
243246
244247 // Chapters
245- var chaptersDiv = $ ( media ) . data ( 'chapters-div' ) ;
248+ var chaptersDiv = data . chaptersDiv ;
246249 if ( chaptersDiv !== undefined && chaptersDiv !== "" ) {
247250 this . chaptersDivLocation = chaptersDiv ;
248251 }
249252
250- if ( $ ( media ) . data ( 'chapters-title' ) !== undefined ) {
253+ if ( data . chaptersTitle !== undefined ) {
251254 // NOTE: empty string is valid; results in no title being displayed
252- this . chaptersTitle = $ ( media ) . data ( 'chapters-title' ) ;
255+ this . chaptersTitle = data . chaptersTitle ;
253256 }
254257
255- var defaultChapter = $ ( media ) . data ( 'chapters-default' ) ;
258+ var defaultChapter = data . chaptersDefault ;
256259 this . defaultChapter = ( defaultChapter !== undefined && defaultChapter !== "" ) ? defaultChapter : null ;
257260
258261 // Slower/Faster buttons
259262 // valid values of data-speed-icons are 'animals' (default) and 'arrows'
260263 // 'animals' uses turtle and rabbit; 'arrows' uses up/down arrows
261- this . speedIcons = ( $ ( media ) . data ( 'speed-icons' ) === 'arrows' ) ? 'arrows' : 'animals' ;
264+ this . speedIcons = ( data . speedIcons === 'arrows' ) ? 'arrows' : 'animals' ;
262265
263266 // Seekbar
264267 // valid values of data-seekbar-scope are 'chapter' and 'video'; will also accept 'chapters'
265- var seekbarScope = $ ( media ) . data ( 'seekbar-scope' ) ;
268+ var seekbarScope = data . seekbarScope ;
266269 this . seekbarScope = ( seekbarScope === 'chapter' || seekbarScope === 'chapters' ) ? 'chapter' : 'video' ;
267270
268271 // YouTube
269- var youTubeId = $ ( media ) . data ( 'youtube-id' ) ;
272+ var youTubeId = data . youTubeId ;
270273 if ( youTubeId !== undefined && youTubeId !== "" ) {
271274 this . youTubeId = this . getYouTubeId ( youTubeId ) ;
272275 if ( ! this . hasPoster ) {
@@ -275,29 +278,29 @@ function ablePlayerSetupWindow() {
275278 }
276279 }
277280
278- var youTubeDescId = $ ( media ) . data ( 'youtube-desc-id' ) ;
281+ var youTubeDescId = data . youTubeDescId ;
279282 if ( youTubeDescId !== undefined && youTubeDescId !== "" ) {
280283 this . youTubeDescId = this . getYouTubeId ( youTubeDescId ) ;
281284 }
282285
283- var youTubeSignId = $ ( media ) . data ( 'youtube-sign-src' ) ;
286+ var youTubeSignId = data . youTubeSignId ;
284287 if ( youTubeSignId !== undefined && youTubeSignId !== "" ) {
285288 this . youTubeSignId = this . getYouTubeId ( youTubeSignId ) ;
286289 }
287290
288- var youTubeNoCookie = $ ( media ) . data ( 'youtube-nocookie' ) ;
291+ var youTubeNoCookie = data . youTubeNoCookie ;
289292 this . youTubeNoCookie = ( youTubeNoCookie !== undefined && youTubeNoCookie ) ? true : false ;
290293
291294 // Vimeo
292- var vimeoId = $ ( media ) . data ( 'vimeo-id' ) ;
295+ var vimeoId = data . vimeoId ;
293296 if ( vimeoId !== undefined && vimeoId !== "" ) {
294297 this . vimeoId = this . getVimeoId ( vimeoId ) ;
295298 if ( ! this . hasPoster ) {
296299 let poster = thisObj . getVimeoPosterUrl ( this . vimeoId , '1200' ) ;
297300 $ ( media ) . attr ( 'poster' , poster ) ;
298301 }
299302 }
300- var vimeoDescId = $ ( media ) . data ( 'vimeo-desc-id' ) ;
303+ var vimeoDescId = data . vimeoDescId ;
301304 if ( vimeoDescId !== undefined && vimeoDescId !== "" ) {
302305 this . vimeoDescId = this . getVimeoId ( vimeoDescId ) ;
303306 }
@@ -306,15 +309,15 @@ function ablePlayerSetupWindow() {
306309 // valid values of data-skin are:
307310 // '2020' (default as of 4.6), all buttons in one row beneath a full-width seekbar
308311 // 'legacy', two rows of controls; seekbar positioned in available space within top row
309- this . skin = ( $ ( media ) . data ( ' skin' ) == 'legacy' ) ? 'legacy' : '2020' ;
312+ this . skin = ( data . skin == 'legacy' ) ? 'legacy' : '2020' ;
310313
311314 // Size
312315 // width of Able Player is determined using the following order of precedence:
313316 // 1. data-width attribute
314317 // 2. width attribute (for video or audio, although it is not valid HTML for audio)
315318 // 3. Intrinsic size from video (video only, determined later)
316- if ( $ ( media ) . data ( ' width' ) !== undefined ) {
317- this . playerWidth = parseInt ( $ ( media ) . data ( ' width' ) ) ;
319+ if ( data . width !== undefined ) {
320+ this . playerWidth = parseInt ( data . width ) ;
318321 } else if ( $ ( media ) [ 0 ] . getAttribute ( 'width' ) ) {
319322 // NOTE: jQuery attr() returns null for all invalid HTML attributes
320323 // (e.g., width on <audio>)
@@ -324,7 +327,7 @@ function ablePlayerSetupWindow() {
324327 this . playerWidth = null ;
325328 }
326329
327- var allowFullScreen = $ ( media ) . data ( 'allow-fullscreen' ) ;
330+ var allowFullScreen = data . allowFullscreen ;
328331 this . allowFullscreen = ( allowFullScreen !== undefined && allowFullScreen === false ) ? false : true ;
329332
330333 // Define other variables that are used in fullscreen program flow
@@ -337,8 +340,8 @@ function ablePlayerSetupWindow() {
337340 // Calculation attempts to intelligently assign a reasonable interval based on media length
338341 this . defaultSeekInterval = 10 ;
339342 this . useFixedSeekInterval = false ; // will change to true if media has valid data-seek-interval attribute
340- if ( $ ( media ) . data ( 'seek-interval' ) !== undefined && $ ( media ) . data ( 'seek-interval' ) !== "" ) {
341- var seekInterval = $ ( media ) . data ( 'seek-interval' ) ;
343+ if ( data . seekInterval !== undefined && data . seekInterval !== "" ) {
344+ var seekInterval = data . seekInterval ;
342345 if ( / ^ [ 1 - 9 ] [ 0 - 9 ] * $ / . test ( seekInterval ) ) { // must be a whole number greater than 0
343346 this . seekInterval = seekInterval ;
344347 this . useFixedSeekInterval = true ; // do not override with calculuation
@@ -348,12 +351,12 @@ function ablePlayerSetupWindow() {
348351 // Now Playing
349352 // Shows "Now Playing:" plus the title of the current track above player
350353 // Only used if there is a playlist
351- var showNowPlaying = $ ( media ) . data ( 'show-now-playing' ) ;
354+ var showNowPlaying = data . showNowPlaying ;
352355 this . showNowPlaying = ( showNowPlaying !== undefined && showNowPlaying === false ) ? false : true ;
353356
354357 // Fallback
355358 // The data-test-fallback attribute can be used to test the fallback solution in any browser
356- var testFallback = $ ( media ) . data ( 'test-fallback' ) ;
359+ var testFallback = data . testFallback ;
357360 if ( testFallback !== undefined && testFallback !== false ) {
358361 // 1: build error; 2: browser doesn't support media.
359362 this . testFallback = ( testFallback == '2' ) ? 2 : 1 ;
@@ -367,45 +370,45 @@ function ablePlayerSetupWindow() {
367370 // 2. Lang attribute on <html> or <body>, if a matching translation file is available
368371 // 3. English
369372 // Final calculation occurs in translation.js > getTranslationText()
370- var lang = $ ( media ) . data ( ' lang' ) ;
373+ var lang = data . lang ;
371374 this . lang = ( lang !== undefined && lang !== "" ) ? lang . toLowerCase ( ) : null ;
372375
373376 // Metadata Tracks
374- var metaType = $ ( media ) . data ( 'meta-type' ) ;
377+ var metaType = data . metaType ;
375378 if ( metaType !== undefined && metaType !== "" ) {
376379 this . metaType = metaType ;
377380 }
378- var metaDiv = $ ( media ) . data ( 'meta-div' ) ;
381+ var metaDiv = data . metaDiv ;
379382 if ( metaDiv !== undefined && metaDiv !== "" ) {
380383 this . metaDiv = metaDiv ;
381384 }
382385
383386 // Search
384387 // conducting a search requires an external div in which to write the results
385- var searchDiv = $ ( media ) . data ( 'search-div' ) ;
388+ var searchDiv = data . searchDiv ;
386389 if ( searchDiv !== undefined && searchDiv !== "" ) {
387390
388391 this . searchDiv = searchDiv ;
389392
390393 // Search term (optional; could be assigned later in a JavaScript application)
391- var searchString = $ ( media ) . data ( ' search' ) ;
394+ var searchString = data . search ;
392395 if ( searchString !== undefined && searchString !== "" ) {
393396 this . searchString = searchString ;
394397 }
395398
396399 // Search Language
397- var searchLang = $ ( media ) . data ( 'search-lang' ) ;
400+ var searchLang = data . searchLang ;
398401 this . searchLang = ( searchLang !== undefined && searchLang !== "" ) ? searchLang : null ;
399402
400403 // Search option: Ignore capitalization in search terms
401- var searchIgnoreCaps = $ ( media ) . data ( 'search-ignore-caps' ) ;
404+ var searchIgnoreCaps = data . searchIgnoreCaps ;
402405 this . searchIgnoreCaps = ( searchIgnoreCaps !== undefined && searchIgnoreCaps !== false ) ? true : false ;
403406 }
404407
405408 // Hide controls when video starts playing
406409 // They will reappear again when user presses a key or moves the mouse
407410 // As of v4.0, controls are hidden automatically on playback in fullscreen mode
408- if ( $ ( media ) . data ( 'hide-controls' ) !== undefined && $ ( media ) . data ( 'hide-controls' ) !== false ) {
411+ if ( data . hideControls !== undefined && data . hideControls !== false ) {
409412 this . hideControls = true ;
410413 this . hideControlsOriginal = true ; // a copy of hideControls, since the former may change if user enters full screen mode
411414 } else {
@@ -416,11 +419,11 @@ function ablePlayerSetupWindow() {
416419 // Steno mode
417420 // Enable support for Able Player keyboard shortcuts in textaarea fields
418421 // so users can control the player while transcribing
419- if ( $ ( media ) . data ( 'steno-mode' ) !== undefined && $ ( media ) . data ( 'steno-mode' ) !== false ) {
422+ if ( data . stenoMode !== undefined && data . stenoMode !== false ) {
420423 this . stenoMode = true ;
421424 // Add support for stenography in an iframe via data-steno-iframe-id
422- if ( $ ( media ) . data ( 'steno-iframe-id' ) !== undefined && $ ( media ) . data ( 'steno-iframe-id' ) !== "" ) {
423- this . stenoFrameId = $ ( media ) . data ( 'steno-iframe-id' ) ;
425+ if ( data . stenoIframeId !== undefined && data . stenoIframeId !== "" ) {
426+ this . stenoFrameId = data . stenoIframeId ;
424427 this . $stenoFrame = $ ( '#' + this . stenoFrameId ) ;
425428 if ( ! ( this . $stenoFrame . length ) ) {
426429 // iframe not found
0 commit comments