|
189 | 189 | this.searchDiv = $(media).data('search-div'); |
190 | 190 | } |
191 | 191 | } |
192 | | - |
| 192 | + |
193 | 193 | this.ableIndex = AblePlayer.nextIndex; |
194 | 194 | AblePlayer.nextIndex += 1; |
195 | 195 |
|
|
553 | 553 |
|
554 | 554 | this.loadCurrentPreferences(); |
555 | 555 | this.injectPlayerCode(); |
| 556 | + this.initSignLanguage(); |
556 | 557 | this.setupTracks().then(function () { |
557 | 558 | thisObj.setupPopups(); |
558 | 559 | thisObj.initDescription(); |
|
946 | 947 | 'label': this.tt.prefCaptions, |
947 | 948 | 'default': 1 // on because many users can benefit |
948 | 949 | }); |
| 950 | + |
| 951 | + prefs.push({ |
| 952 | + 'name': 'prefSignLanguage', // use sign language if available |
| 953 | + 'label': this.tt.prefSignLanguage, |
| 954 | + 'default': 1 // on because in rare cases that it's actually available, users should be exposed to it |
| 955 | + }); |
949 | 956 |
|
950 | 957 | prefs.push({ |
951 | 958 | 'name': 'prefDesc', // audio description default state |
|
2145 | 2152 | if (this.transcriptDivLocation) { |
2146 | 2153 | $('#' + this.transcriptDivLocation).append(this.$transcriptArea); |
2147 | 2154 | } |
| 2155 | + else if (this.$ableColumnRight) { |
| 2156 | + this.$ableColumnRight.prepend(this.$transcriptArea); |
| 2157 | + } |
2148 | 2158 | else { |
2149 | | - // Place adjacent to player with reactive flow. |
2150 | | - this.$ableColumnLeft = this.$ableDiv.wrap('<div class="able-column-left">').parent(); |
2151 | | - this.$ableColumnLeft.width(this.playerWidth); |
2152 | | - this.$transcriptArea.insertAfter(this.$ableColumnLeft); |
2153 | | - this.$ableColumnRight = this.$transcriptArea.wrap('<div class="able-column-right">').parent(); |
2154 | | - this.$ableColumnRight.width(this.playerWidth); |
| 2159 | + this.splitPlayerIntoColumns('transcript'); |
2155 | 2160 | } |
2156 | | - |
| 2161 | + |
2157 | 2162 | // If client has provided separate transcript location, override user's preference for hiding transcript |
2158 | 2163 | if (!this.prefTranscript && !this.transcriptDivLocation) { |
2159 | 2164 | this.$transcriptArea.hide(); |
2160 | 2165 | } |
2161 | 2166 | }; |
2162 | 2167 |
|
| 2168 | + AblePlayer.prototype.splitPlayerIntoColumns = function (feature) { |
| 2169 | + // feature is either 'transcript' or 'sign' |
| 2170 | + // if present, player is split into two column, with this feature in the right column |
| 2171 | + this.$ableColumnLeft = this.$ableDiv.wrap('<div class="able-column-left">').parent(); |
| 2172 | + this.$ableColumnLeft.width(this.playerWidth); |
| 2173 | + if (feature === 'transcript') { |
| 2174 | + this.$transcriptArea.insertAfter(this.$ableColumnLeft); |
| 2175 | + this.$ableColumnRight = this.$transcriptArea.wrap('<div class="able-column-right">').parent(); |
| 2176 | + } |
| 2177 | + else if (feature == 'sign') { |
| 2178 | + this.$signArea.insertAfter(this.$ableColumnLeft); |
| 2179 | + this.$ableColumnRight = this.$signArea.wrap('<div class="able-column-right">').parent(); |
| 2180 | + } |
| 2181 | + this.$ableColumnRight.width(this.playerWidth); |
| 2182 | + }; |
| 2183 | + |
2163 | 2184 | AblePlayer.prototype.injectAlert = function () { |
2164 | 2185 | this.alertBox = $('<div role="alert"></div>'); |
2165 | 2186 | this.alertBox.addClass('able-tooltip'); |
|
2652 | 2673 | if (this.hasCaptions) { |
2653 | 2674 | blr.push('captions'); //closed captions |
2654 | 2675 | } |
2655 | | - if (this.hasOpenDesc || this.hasClosedDesc) { |
2656 | | - blr.push('descriptions'); //audio description |
2657 | | - } |
2658 | 2676 | if (this.hasSignLanguage) { |
2659 | 2677 | blr.push('sign'); // sign language |
2660 | 2678 | } |
| 2679 | + if (this.hasOpenDesc || this.hasClosedDesc) { |
| 2680 | + blr.push('descriptions'); //audio description |
| 2681 | + } |
2661 | 2682 | } |
2662 | 2683 |
|
2663 | 2684 | if (this.includeTranscript && this.useTranscriptButton) { |
|
2902 | 2923 | else if (control === 'captions') { |
2903 | 2924 | this.$ccButton = newButton; |
2904 | 2925 | } |
| 2926 | + else if (control === 'sign') { |
| 2927 | + this.$signButton = newButton; |
| 2928 | + } |
2905 | 2929 | else if (control === 'descriptions') { |
2906 | 2930 | this.$descButton = newButton; |
2907 | 2931 | // gray out description button if description is not active |
|
3113 | 3137 | else if (control === 'chapters') { |
3114 | 3138 | return this.tt.chapters; |
3115 | 3139 | } |
3116 | | - else if (control === 'sign') { // not yet supported |
| 3140 | + else if (control === 'sign') { |
3117 | 3141 | return this.tt.sign; |
3118 | 3142 | } |
3119 | 3143 | else if (control === 'mute') { |
|
4271 | 4295 |
|
4272 | 4296 | if (seekable.length > 0 && this.startTime >= seekable.start(0) && this.startTime <= seekable.end(0)) { |
4273 | 4297 | this.media.currentTime = this.startTime; |
| 4298 | + |
| 4299 | + if (this.hasSignLanguage && this.signVideo) { |
| 4300 | + // keep sign languge video in sync |
| 4301 | + this.signVideo.currentTime = this.startTime; |
| 4302 | + } |
| 4303 | + |
4274 | 4304 | } |
4275 | 4305 | } |
4276 | 4306 | else if (this.player === 'jw') { |
|
4453 | 4483 |
|
4454 | 4484 | if (this.player === 'html5') { |
4455 | 4485 | this.media.volume = volume; |
| 4486 | + if (this.hasSignLanguage && this.signVideo) { |
| 4487 | + this.signVideo.volume = 0; // always mute |
| 4488 | + } |
4456 | 4489 | } |
4457 | 4490 | else if (this.player === 'jw') { |
4458 | 4491 | this.jwPlayer.setVolume(volume * 100); |
|
4529 | 4562 | AblePlayer.prototype.pauseMedia = function () { |
4530 | 4563 | if (this.player === 'html5') { |
4531 | 4564 | this.media.pause(true); |
| 4565 | + if (this.hasSignLanguage && this.signVideo) { |
| 4566 | + this.signVideo.pause(true); |
| 4567 | + } |
4532 | 4568 | } |
4533 | 4569 | else if (this.player === 'jw') { |
4534 | 4570 | this.jwPlayer.pause(true); |
|
4541 | 4577 | AblePlayer.prototype.playMedia = function () { |
4542 | 4578 | if (this.player === 'html5') { |
4543 | 4579 | this.media.play(true); |
| 4580 | + if (this.hasSignLanguage && this.signVideo) { |
| 4581 | + this.signVideo.play(true); |
| 4582 | + } |
4544 | 4583 | } |
4545 | 4584 | else if (this.player === 'jw') { |
4546 | 4585 | this.jwPlayer.play(true); |
|
5055 | 5094 | } |
5056 | 5095 | }; |
5057 | 5096 |
|
| 5097 | + AblePlayer.prototype.handleSignToggle = function () { |
| 5098 | + if (this.$signWindow.is(':visible')) { |
| 5099 | + this.$signWindow.hide(); |
| 5100 | + this.$signButton.addClass('buttonOff').attr('aria-label',this.tt.showSign); |
| 5101 | + this.$signButton.find('span.able-clipped').text(this.tt.showSign); |
| 5102 | + } |
| 5103 | + else { |
| 5104 | + this.$signWindow.show(); |
| 5105 | + this.$signButton.removeClass('buttonOff').attr('aria-label',this.tt.hideSign); |
| 5106 | + this.$signButton.find('span.able-clipped').text(this.tt.hideSign); |
| 5107 | + } |
| 5108 | + }; |
| 5109 | + |
5058 | 5110 | AblePlayer.prototype.isFullscreen = function () { |
5059 | 5111 | if (this.nativeFullscreenSupported()) { |
5060 | 5112 | return (document.fullscreenElement || |
|
6062 | 6114 | else if (whichButton === 'descriptions') { |
6063 | 6115 | this.handleDescriptionToggle(); |
6064 | 6116 | } |
6065 | | - else if (whichButton.substr(0,4) === 'sign') { |
6066 | | - // not yet supported |
| 6117 | + else if (whichButton === 'sign') { |
| 6118 | + this.handleSignToggle(); |
6067 | 6119 | } |
6068 | 6120 | else if (whichButton === 'preferences') { |
6069 | 6121 | this.handlePrefsClick(); |
|
6423 | 6475 | } |
6424 | 6476 | }; |
6425 | 6477 | })(jQuery); |
| 6478 | + |
| 6479 | +(function ($) { |
| 6480 | + AblePlayer.prototype.initSignLanguage = function() { |
| 6481 | + |
| 6482 | + // only initialize sign language if user wants it |
| 6483 | + // since it requires downloading a second video & consumes bandwidth |
| 6484 | + if (this.prefSignLanguage) { |
| 6485 | + // check to see if there's a sign language video accompanying this video |
| 6486 | + // check only the first source |
| 6487 | + // If sign language is provided, it must be provided for all sources |
| 6488 | + this.signFile = this.$sources.first().attr('data-sign-src'); |
| 6489 | + if (this.signFile) { |
| 6490 | + if (this.debug) { |
| 6491 | + |
| 6492 | + } |
| 6493 | + this.hasSignLanguage = true; |
| 6494 | + this.injectSignPlayerCode(); |
| 6495 | + } |
| 6496 | + else { |
| 6497 | + this.hasSignLanguage = false; |
| 6498 | + } |
| 6499 | + } |
| 6500 | + }; |
| 6501 | + |
| 6502 | + AblePlayer.prototype.injectSignPlayerCode = function() { |
| 6503 | + |
| 6504 | + // create and inject surrounding HTML structure |
| 6505 | + // If IOS: |
| 6506 | + // If video: |
| 6507 | + // IOS does not support any of the player's functionality |
| 6508 | + // - everything plays in its own player |
| 6509 | + // Therefore, AblePlayer is not loaded & all functionality is disabled |
| 6510 | + // (this all determined. If this is IOS && video, this function is never called) |
| 6511 | + // If audio: |
| 6512 | + // HTML cannot be injected as a *parent* of the <audio> element |
| 6513 | + // It is therefore injected *after* the <audio> element |
| 6514 | + // This is only a problem in IOS 6 and earlier, |
| 6515 | + // & is a known bug, fixed in IOS 7 |
| 6516 | + |
| 6517 | + var thisObj, signVideoId, i, signSrc, srcType, $signSource; |
| 6518 | + |
| 6519 | + thisObj = this; |
| 6520 | + |
| 6521 | + signVideoId = this.mediaId + '-sign'; |
| 6522 | + this.$signVideo = $('<video>',{ |
| 6523 | + 'id' : signVideoId, |
| 6524 | + 'width' : this.playerWidth |
| 6525 | + }); |
| 6526 | + this.signVideo = this.$signVideo[0]; |
| 6527 | + // for each original <source>, add a <source> to the sign <video> |
| 6528 | + for (i=0; i < this.$sources.length; i++) { |
| 6529 | + signSrc = this.$sources[i].getAttribute('data-sign-src'); |
| 6530 | + srcType = this.$sources[i].getAttribute('type'); |
| 6531 | + if (signSrc) { |
| 6532 | + $signSource = $('<source>',{ |
| 6533 | + 'src' : signSrc, |
| 6534 | + 'type' : srcType |
| 6535 | + }); |
| 6536 | + this.$signVideo.append($signSource); |
| 6537 | + } |
| 6538 | + else { |
| 6539 | + // source is missing a sign language version |
| 6540 | + // can't include sign language |
| 6541 | + this.hasSignLanguage = false; |
| 6542 | + break; |
| 6543 | + } |
| 6544 | + } |
| 6545 | + |
| 6546 | + // TODO: Consider whether width x height should be added to the sign window, or the video element |
| 6547 | + this.$signWindow = $('<div>',{ |
| 6548 | + 'class' : 'able-sign-window', |
| 6549 | + }); |
| 6550 | + this.$signWindow.append(this.$signVideo).hide(); |
| 6551 | + |
| 6552 | + // Place sign window in div.able-column-right |
| 6553 | + // If div doesn't exist yet, create it |
| 6554 | + if (this.$ableColumnRight) { |
| 6555 | + this.$ableColumnRight.append(this.$signWindow); |
| 6556 | + } |
| 6557 | + else { |
| 6558 | + this.splitPlayerIntoColumns('sign'); |
| 6559 | + } |
| 6560 | + |
| 6561 | + this.addSignEvents(); |
| 6562 | + }; |
| 6563 | + |
| 6564 | + AblePlayer.prototype.addSignEvents = function() { |
| 6565 | + |
| 6566 | + // populate with functions to handle click and drag on sign window |
| 6567 | + }; |
| 6568 | + |
| 6569 | +})(jQuery); |
0 commit comments