Skip to content

Commit

Permalink
Get options working, Update Docs
Browse files Browse the repository at this point in the history
  • Loading branch information
walsh9 committed Oct 11, 2014
1 parent 2925b7d commit 282520b
Show file tree
Hide file tree
Showing 10 changed files with 170 additions and 81 deletions.
77 changes: 55 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,9 @@

Creates interactive transcripts from text tracks.

## Warning

:no_entry: **Warning! This code is an early work in progress and contains bugs, typos, unimplemented features, debug cruft, and other defects. Don't use it yet.**

### TODO:
- [x] Seek video to transcript position when transcript is clicked
- [ ] Add more setup options
- [x] Nicer default CSS
- [x] More CSS examples
- [x] Handle multiple tracks
- [x] Automatically switch caption track when user selects a different track on the video.
- [x] Separate track switcher
- [x] Autoscrolling transcript
- [x] *Smooth*, animated scrolling
- [x] Clean up scrolling logic.
- [x] Prevent autoscrolling when user is interacting with transcript (nice to have)
- [x] Tests!
- [ ] More Tests!
- [ ] More...
## Alpha Release 1

Please report any issues or feature requests on the tracker. Thank you!

## Getting Started

Expand All @@ -29,13 +13,33 @@ Once you've added the plugin script to your page, you can use it with any video:
```html
<script src="video.js"></script>
<script src="videojs-transcript.js"></script>
<video id="video">
<source src="whatever.webm" type="video/webm">
<track kind="captions" src="mycaptions.srt" srclang="en" label="English" default>
</video>
<div id="transcript"></div>
<script>
videojs(document.querySelector('video')).transcript();
var video = videojs('video');
// Set up any options.
var options = {
showTitle: false,
showTrackSelector: false,
});
// Initialize the plugin.
var transcript = video.transcript(options);
// Then attach the widget to the page.
var transcriptContainer = document.querySelector('#transcript');
transcriptContainer.appendChild(transcript.el());
</script>
```

There's also a [working example](example.html) of the plugin you can check out if you're having trouble.

You'll also want to include one of the css files.
You can style the plugin as you like but there are a few examples in the /css folder to get you started.

## Documentation
### Plugin Options

Expand All @@ -53,6 +57,35 @@ Set to false to disable autoscrolling.
Set which elements in the transcript are clickable.
Options are 'timestamp', 'text', the whole 'line', or 'none'.

#### showTitle
**Default:** true

Show a title with the transcript widget.

(Currently the title only says 'Transcript')

#### showTrackSelector
**Default:** true

Show a track selector with the transcript widget.

#### followPlayerTrack
**Default:** true

When you change the caption track on the video, the transcript changes tracks as well.

#### stopScrollWhenInUse
**Default:** true

Don't autoscroll the transcript when the user is trying to scroll it.

(This probably still has a few glitches to work out on touch screens and stuff right now)

### Plugin Methods
**el()**

Returns the DOM element containing the html transcript widget. You'll need to append this to your page.

## Release History

- 0.1.0: Initial release
- 0.7.1: Alpha Release 1
31 changes: 26 additions & 5 deletions css/videojs-transcript3.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
.video-container {
margin: 40px auto;
position: relative;
width: 900px;
}
#video {
margin: 0;
position: absolute;
}
#transcript {
width: 600px;
margin: auto;
position: absolute;
left: 600px;
width: 298px;
font-family: Arial, sans-serif;
overflow-x: scroll;
height: 298px;
border: 1px solid #111;
}
.transcript-header {
height: 19px;
padding: 2px;
font-weight: bold;
}
.transcript-selector {
height: 25px;
}

.transcript-body {
height: 200px;
width: 600px;
overflow-y: scroll;
border: 1px solid #111;
background-color: #e7e7e7;
height: 250px;
}

.transcript-line {
Expand Down Expand Up @@ -49,3 +69,4 @@
color: #e7e7e7;
}


49 changes: 33 additions & 16 deletions dist/videojs-transcript.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*! videojs-transcript - v0.0.0 - 2014-10-08
/*! videojs-transcript - v0.7.1 - 2014-10-10
* Copyright (c) 2014 Matthew Walsh; Licensed MIT */
(function (window, videojs) {
'use strict';
Expand Down Expand Up @@ -78,6 +78,12 @@ if (!Array.prototype.forEach) {
};
}

// classList polyfill
/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/
;if("document" in self&&!("classList" in document.createElement("_"))){(function(j){"use strict";if(!("Element" in j)){return}var a="classList",f="prototype",m=j.Element[f],b=Object,k=String[f].trim||function(){return this.replace(/^\s+|\s+$/g,"")},c=Array[f].indexOf||function(q){var p=0,o=this.length;for(;p<o;p++){if(p in this&&this[p]===q){return p}}return -1},n=function(o,p){this.name=o;this.code=DOMException[o];this.message=p},g=function(p,o){if(o===""){throw new n("SYNTAX_ERR","An invalid or illegal string was specified")}if(/\s/.test(o)){throw new n("INVALID_CHARACTER_ERR","String contains an invalid character")}return c.call(p,o)},d=function(s){var r=k.call(s.getAttribute("class")||""),q=r?r.split(/\s+/):[],p=0,o=q.length;for(;p<o;p++){this.push(q[p])}this._updateClassName=function(){s.setAttribute("class",this.toString())}},e=d[f]=[],i=function(){return new d(this)};n[f]=Error[f];e.item=function(o){return this[o]||null};e.contains=function(o){o+="";return g(this,o)!==-1};e.add=function(){var s=arguments,r=0,p=s.length,q,o=false;do{q=s[r]+"";if(g(this,q)===-1){this.push(q);o=true}}while(++r<p);if(o){this._updateClassName()}};e.remove=function(){var t=arguments,s=0,p=t.length,r,o=false;do{r=t[s]+"";var q=g(this,r);if(q!==-1){this.splice(q,1);o=true}}while(++s<p);if(o){this._updateClassName()}};e.toggle=function(p,q){p+="";var o=this.contains(p),r=o?q!==true&&"remove":q!==false&&"add";if(r){this[r](p)}return !o};e.toString=function(){return this.join(" ")};if(b.defineProperty){var l={get:i,enumerable:true,configurable:true};try{b.defineProperty(m,a,l)}catch(h){if(h.number===-2146823252){l.enumerable=false;b.defineProperty(m,a,l)}}}else{if(b[f].__defineGetter__){m.__defineGetter__(a,i)}}}(self))};



// Global settings
var my = {};
my.settings = {};
Expand All @@ -87,7 +93,11 @@ my.player = this;
// Defaults
var defaults = {
autoscroll: true,
clickArea: 'line'
clickArea: 'text',
showTitle: true,
showTrackSelector: true,
followPlayerTrack: true,
stopScrollWhenInUse: true,
};

/*global my*/
Expand Down Expand Up @@ -234,17 +244,18 @@ var scrollerProto = function(plugin) {
var parent = element.parentElement;
var parentOffsetBottom = parent.offsetTop + parent.clientHeight;
var elementOffsetBottom = element.offsetTop + element.clientHeight;
var relPos = element.offsetTop - parent.offsetTop;
var relTop = element.offsetTop - parent.offsetTop;
var relBottom = (element.offsetTop + element.clientHeight) - parent.offsetTop;
var newPos;

// If the line is above the top of the parent view, were scrolling up,
// 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 (relPos < parent.scrollTop) {
if (relTop < parent.scrollTop) {
newPos = element.offsetTop - parent.offsetTop;

// If the line is below the parent view, we're scrolling down, so we want the
// 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 (relPos > (parent.scrollTop + parent.clientHeight)) {
} else if (relBottom > (parent.scrollTop + parent.clientHeight)) {
newPos = elementOffsetBottom - parentOffsetBottom;
}

Expand Down Expand Up @@ -345,8 +356,8 @@ var widget = function (plugin) {
var clickedTime = event.target.getAttribute('data-begin') || event.target.parentElement.getAttribute('data-begin');
if (clickedTime !== undefined && clickedTime !== null) { // can be zero
if ((plugin.settings.clickArea === 'line') || // clickArea: 'line' activates on all elements
(plugin.settings.clickArea === 'timestamp' && clickedClasses.contains(myPrefix + '-timestamp')) ||
(plugin.settings.clickArea === 'text' && clickedClasses.contains(myPrefix + '-text'))) {
(plugin.settings.clickArea === 'timestamp' && clickedClasses.contains(plugin.prefix + '-timestamp')) ||
(plugin.settings.clickArea === 'text' && clickedClasses.contains(plugin.prefix + '-text'))) {
plugin.player.currentTime(clickedTime);
}
}
Expand Down Expand Up @@ -393,10 +404,14 @@ var widget = function (plugin) {
var el = document.createElement('div');
my.element = el;
el.setAttribute('id', plugin.prefix + '-' + plugin.player.id());
var title = createTitle();
el.appendChild(title);
var selector = createSelector();
el.appendChild(selector);
if (plugin.settings.showTitle) {
var title = createTitle();
el.appendChild(title);
}
if (plugin.settings.showTrackSelector) {
var selector = createSelector();
el.appendChild(selector);
}
my.body = utils.createEl('div', '-body');
el.appendChild(my.body);
setTrack(plugin.currentTrack);
Expand All @@ -421,7 +436,7 @@ var widget = function (plugin) {
if (time > begin && time < end) {
if (!line.classList.contains('is-active')) { // don't update if it hasn't changed
line.classList.add('is-active');
if (plugin.settings.autoscroll && !my.body.scroll.inUse()) {
if (plugin.settings.autoscroll && !(plugin.settings.stopScrollWhenInUse && my.body.scroll.inUse())) {
my.body.scroll.to(line);
}
}
Expand Down Expand Up @@ -460,8 +475,10 @@ var transcript = function (options) {
if (my.validTracks.length > 0) {
updateTrack();
my.player.on('timeupdate', timeUpdate);
my.player.on('captionstrackchange', updateTrack);
my.player.on('subtitlestrackchange', updateTrack);
if (my.settings.followPlayerTrack) {
my.player.on('captionstrackchange', updateTrack);
my.player.on('subtitlestrackchange', updateTrack);
}
} else {
throw new Error('videojs-transcript: No tracks found!');
}
Expand Down
Loading

0 comments on commit 282520b

Please sign in to comment.