diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..b426684 --- /dev/null +++ b/bower.json @@ -0,0 +1,21 @@ +{ + "name": "videojs-transcript", + "version": "0.8.1", + "dependencies": { + "video.js": "^5.6.0" + }, + "homepage": "https://github.com/walsh9/videojs-transcript", + "authors": [ + "walsh9" + ], + "description": "", + "main": "", + "license": "MIT", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ] +} diff --git a/dist/videojs-transcript.js b/dist/videojs-transcript.js index 7cd9bd6..a21c007 100644 --- a/dist/videojs-transcript.js +++ b/dist/videojs-transcript.js @@ -1,5 +1,5 @@ -/*! videojs-transcript - v0.8.0 - 2016-02-21 -* Copyright (c) 2016 Matthew Walsh; Licensed MIT */ +/*! videojs-transcript - v0.8.1 - 2017-04-21 +* Copyright (c) 2017 Matthew Walsh; Licensed MIT */ (function (window, videojs) { 'use strict'; @@ -376,6 +376,7 @@ var widget = function (plugin) { var timestamp = utils.createEl('span', '-timestamp'); var text = utils.createEl('span', '-text'); line.setAttribute('data-begin', cue.startTime); + line.setAttribute('tabindex', my._options.tabIndex || 0); timestamp.textContent = utils.secondsToTime(cue.startTime); text.innerHTML = cue.text; line.appendChild(timestamp); @@ -415,8 +416,9 @@ var widget = function (plugin) { } }; - var create = function () { + var create = function (options) { var el = document.createElement('div'); + my._options = options; my.element = el; el.setAttribute('id', plugin.prefix + '-' + plugin.player.id()); if (plugin.settings.showTitle) { @@ -477,7 +479,7 @@ var transcript = function (options) { my.validTracks = trackList.get(); my.currentTrack = trackList.active(my.validTracks); my.settings = videojs.mergeOptions(defaults, options); - my.widget = widget.create(); + my.widget = widget.create(options); var timeUpdate = function () { my.widget.setCue(my.player.currentTime()); }; diff --git a/dist/videojs-transcript.min.js b/dist/videojs-transcript.min.js index 03c5356..b80c35a 100644 --- a/dist/videojs-transcript.min.js +++ b/dist/videojs-transcript.min.js @@ -1,3 +1,3 @@ -/*! videojs-transcript - v0.8.0 - 2016-02-21 -* Copyright (c) 2016 Matthew Walsh; Licensed MIT */ -!function(a,b){"use strict";!function(){for(var b=0,c=["ms","moz","webkit","o"],d=0;d1)throw Error("Second argument not supported");if("object"!=typeof b)throw TypeError("Argument must be an object");a.prototype=b;var c=new a;return a.prototype=null,c}}()),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c,d;if(null==this)throw new TypeError(" this is null or not defined");var e=Object(this),f=e.length>>>0;if("function"!=typeof a)throw new TypeError(a+" is not a function");for(arguments.length>1&&(c=b),d=0;d0&&c<10?"0"+c:c,b>0?b+":"+c+":"+d:c+":"+d},localize:function(a){return a},createEl:function(b,c){c=c||"";var d=document.createElement(b);return d.className=a.prefix+c,d},extend:function(a){var b=typeof a;if(!("function"===b||"object"===b&&a))return a;for(var c,d,e=1,f=arguments.length;ec.scrollTop+c.clientHeight-i&&(j=f-d+i),void 0!==j&&c.scrollTop!==j&&e.call(this,c,j,400)}},g=function(){var a=this.element;return a.scrollHeight>a.offsetHeight},h=function(){return this.userIsScrolling};return{init:c,to:f,canScroll:g,inUse:h}}(c),h=function(a){return Object.create(g).init(a)},i=function(a){var b;return{get:function(){var b,d,a=[];for(c.tracks=c.player.textTracks(),b=0;bg&&a0))throw new Error("videojs-transcript: No tracks found!");return f(),c.player.on("timeupdate",e),c.settings.followPlayerTrack&&(c.player.on("captionstrackchange",f),c.player.on("subtitlestrackchange",f)),{el:function(){return c.widget.el()},setTrack:c.widget.setTrack}};b.plugin("transcript",k)}(window,videojs); +/*! videojs-transcript - v0.8.1 - 2017-04-21 +* Copyright (c) 2017 Matthew Walsh; Licensed MIT */ +!function(a,b){"use strict";!function(){for(var b=0,c=["ms","moz","webkit","o"],d=0;d1)throw Error("Second argument not supported");if("object"!=typeof b)throw TypeError("Argument must be an object");a.prototype=b;var c=new a;return a.prototype=null,c}}()),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c,d;if(null==this)throw new TypeError(" this is null or not defined");var e=Object(this),f=e.length>>>0;if("function"!=typeof a)throw new TypeError(a+" is not a function");for(arguments.length>1&&(c=b),d=0;f>d;){var g;d in e&&(g=e[d],a.call(c,g,d,e)),d++}}),"document"in self&&!("classList"in document.createElement("_"))&&!function(a){if("Element"in a){var b="classList",c="prototype",d=a.Element[c],e=Object,f=String[c].trim||function(){return this.replace(/^\s+|\s+$/g,"")},g=Array[c].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1},h=function(a,b){this.name=a,this.code=DOMException[a],this.message=b},i=function(a,b){if(""===b)throw new h("SYNTAX_ERR","An invalid or illegal string was specified");if(/\s/.test(b))throw new h("INVALID_CHARACTER_ERR","String contains an invalid character");return g.call(a,b)},j=function(a){for(var b=f.call(a.getAttribute("class")||""),c=b?b.split(/\s+/):[],d=0,e=c.length;e>d;d++)this.push(c[d]);this._updateClassName=function(){a.setAttribute("class",this.toString())}},k=j[c]=[],l=function(){return new j(this)};if(h[c]=Error[c],k.item=function(a){return this[a]||null},k.contains=function(a){return a+="",-1!==i(this,a)},k.add=function(){var a,b=arguments,c=0,d=b.length,e=!1;do a=b[c]+"",-1===i(this,a)&&(this.push(a),e=!0);while(++cd?"0"+d:d,c=b>0&&10>c?"0"+c:c,b>0?b+":"+c+":"+d:c+":"+d},localize:function(a){return a},createEl:function(b,c){c=c||"";var d=document.createElement(b);return d.className=a.prefix+c,d},extend:function(a){var b=typeof a;if(!("function"===b||"object"===b&&a))return a;for(var c,d,e=1,f=arguments.length;f>e;e++){c=arguments[e];for(d in c)a[d]=c[d]}return a}}}(c),f={handlers_:[],on:function(a,b,c){if("function"!=typeof c)throw new TypeError("Callback is not a function.");this.handlers_.push([a,b,c])},trigger:function(a,b){this.handlers_.forEach(function(c){c[0]===a&&c[1]===b&&c[2].apply()})}},g=function(a){var b=function(a){var b=this;a.addEventListener("scroll",function(){b.isAutoScrolling?b.isAutoScrolling=!1:(b.userIsScrolling=!0,a.classList.add("is-inuse"))}),a.addEventListener("mouseenter",function(){b.mouseIsOverTranscript=!0}),a.addEventListener("mouseleave",function(){b.mouseIsOverTranscript=!1,setTimeout(function(){b.mouseIsOverTranscript||(b.userIsScrolling=!1,a.classList.remove("is-inuse"))},1e3)})},c=function(a,c){return this.element=a,this.userIsScrolling=!1,this.mouseIsOverTranscript=!0,this.isAutoScrolling=!0,b.call(this,this.element),this},d=function(a,b,c,d){return b+c*Math.sin(Math.min(1,a/d)*(Math.PI/2))},e=function(a,b,c){var e=Date.now(),f=a.scrollTop,g=this;b=Math.max(0,b),b=Math.min(a.scrollHeight-a.clientHeight,b);var h=b-f,i=function(){var j=Date.now(),k=j-e;g.isAutoScrolling=!0,a.scrollTop=d(k,f,h,c),a.scrollTop!==b&&requestAnimationFrame(i,a)};requestAnimationFrame(i,a)},f=function(b){if(this.canScroll()){var c,d=b.parentElement,f=d.offsetTop+d.clientHeight,g=b.offsetTop+b.clientHeight,h=b.offsetTop-d.offsetTop,i=b.offsetTop+b.clientHeight-d.offsetTop,j=0;a.settings.scrollToCenter&&(j=Math.round(d.clientHeight/2-b.clientHeight/2)),hd.scrollTop+d.clientHeight-j&&(c=g-f+j),void 0!==c&&d.scrollTop!==c&&e.call(this,d,c,400)}},g=function(){var a=this.element;return a.scrollHeight>a.offsetHeight},h=function(){return this.userIsScrolling};return{init:c,to:f,canScroll:g,inUse:h}}(c),h=function(a){return Object.create(g).init(a)},i=function(a){var b;return{get:function(){var a,b,d=[];for(c.tracks=c.player.textTracks(),a=0;af&&g>a?e.classList.contains("is-active")||(e.classList.add("is-active"),!b.settings.autoscroll||b.settings.stopScrollWhenInUse&&c.body.scroll.inUse()||c.body.scroll.to(e)):e.classList.remove("is-active")},q=function(){return c.element};return{create:n,setTrack:o,setCue:p,el:q,on:d,trigger:g}}(c),k=function(a){c.player=this,c.validTracks=i.get(),c.currentTrack=i.active(c.validTracks),c.settings=b.mergeOptions(d,a),c.widget=j.create(a);var e=function(){c.widget.setCue(c.player.currentTime())},f=function(){c.currentTrack=i.active(c.validTracks),c.widget.setTrack(c.currentTrack)};if(!(c.validTracks.length>0))throw new Error("videojs-transcript: No tracks found!");return f(),c.player.on("timeupdate",e),c.settings.followPlayerTrack&&(c.player.on("captionstrackchange",f),c.player.on("subtitlestrackchange",f)),{el:function(){return c.widget.el()},setTrack:c.widget.setTrack}};b.plugin("transcript",k)}(window,videojs); \ No newline at end of file diff --git a/package.json b/package.json index 261827b..974c909 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "videojs-transcript", - "version": "0.8.0", + "version": "0.8.1", "author": "Matthew Walsh", "description": "Creates interactive transcripts from text tracks.", "license": "MIT", diff --git a/src/main.js b/src/main.js index d987b87..a7793f2 100644 --- a/src/main.js +++ b/src/main.js @@ -4,7 +4,7 @@ var transcript = function (options) { my.validTracks = trackList.get(); my.currentTrack = trackList.active(my.validTracks); my.settings = videojs.mergeOptions(defaults, options); - my.widget = widget.create(); + my.widget = widget.create(options); var timeUpdate = function () { my.widget.setCue(my.player.currentTime()); }; diff --git a/src/options.js b/src/options.js index 2d0b394..76f8b8a 100644 --- a/src/options.js +++ b/src/options.js @@ -15,5 +15,6 @@ var defaults = { showTitle: true, showTrackSelector: true, followPlayerTrack: true, + scrollToCenter: false, stopScrollWhenInUse: true, }; diff --git a/src/scroller.js b/src/scroller.js index fb4f54c..9e290c8 100644 --- a/src/scroller.js +++ b/src/scroller.js @@ -88,17 +88,21 @@ var scrollerProto = function(plugin) { var elementOffsetBottom = element.offsetTop + element.clientHeight; var relTop = element.offsetTop - parent.offsetTop; var relBottom = (element.offsetTop + element.clientHeight) - parent.offsetTop; + var centerPosCorrection = 0; var newPos; + if (plugin.settings.scrollToCenter){ + centerPosCorrection = Math.round(parent.clientHeight/2 - element.clientHeight/2); + } // If the top of the line is above the top of the parent view, were scrolling up, // so we want to move the top of the element downwards to match the top of the parent. - if (relTop < parent.scrollTop) { - newPos = element.offsetTop - parent.offsetTop; + if (relTop < parent.scrollTop + centerPosCorrection) { + newPos = element.offsetTop - parent.offsetTop -centerPosCorrection; // If the bottom of the line is below the parent view, we're scrolling down, so we want the // bottom edge of the line to move up to meet the bottom edge of the parent. - } else if (relBottom > (parent.scrollTop + parent.clientHeight)) { - newPos = elementOffsetBottom - parentOffsetBottom; + } else if (relBottom > (parent.scrollTop + parent.clientHeight) - centerPosCorrection) { + newPos = elementOffsetBottom - parentOffsetBottom + centerPosCorrection; } // Don't try to scroll if we haven't set a new position. If we didn't diff --git a/src/widget.js b/src/widget.js index 3b26c0e..15d4e6f 100644 --- a/src/widget.js +++ b/src/widget.js @@ -49,6 +49,7 @@ var widget = function (plugin) { var timestamp = utils.createEl('span', '-timestamp'); var text = utils.createEl('span', '-text'); line.setAttribute('data-begin', cue.startTime); + line.setAttribute('tabindex', my._options.tabIndex || 0); timestamp.textContent = utils.secondsToTime(cue.startTime); text.innerHTML = cue.text; line.appendChild(timestamp); @@ -88,8 +89,9 @@ var widget = function (plugin) { } }; - var create = function () { + var create = function (options) { var el = document.createElement('div'); + my._options = options; my.element = el; el.setAttribute('id', plugin.prefix + '-' + plugin.player.id()); if (plugin.settings.showTitle) {