-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
VP-211: subtitlesFinder component for a VideoPlayer #125
base: main
Are you sure you want to change the base?
Changes from 1 commit
02560be
c1450b7
53d215f
c93087d
4ce84ac
8cd58ed
349b267
b384b92
f4f6e43
4eb8e6d
abe30ff
f07847c
82b22ec
0488d2f
81f19fe
f9b89a6
544a360
c37ebf0
95a94f5
57fb6b3
c645cbc
a7b2da5
e907342
12d1a5f
4d8e90a
a9f073b
4bf4f2e
5d024dd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
…niSubComponent. Based on the acheetham branch https://github.com/acheetham/videoPlayer/tree/FLUID-4851
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,7 +34,6 @@ var fluid_1_5 = fluid_1_5 || {}; | |
postInitFunction: "fluid.videoPlayer.languageMenu.postInit", | ||
finalInitFunction: "fluid.videoPlayer.languageMenu.finalInit", | ||
produceTree: "fluid.videoPlayer.languageMenu.produceTree", | ||
languages: [], | ||
currentLanguagePath: "activeLanguages", | ||
showHidePath: "showLanguage", | ||
model: {}, | ||
|
@@ -48,7 +47,8 @@ var fluid_1_5 = fluid_1_5 || {}; | |
}, | ||
activated: null, | ||
hiddenByKeyboard: null, | ||
onControlledElementReady: null | ||
onControlledElementReady: null, | ||
onLanguageListUpdated: null | ||
}, | ||
listeners: { | ||
onControlledElementReady: { | ||
|
@@ -80,14 +80,12 @@ var fluid_1_5 = fluid_1_5 || {}; | |
// TODO: Could this be specified declaratively, in a "protoTree" option? | ||
// Ans: not very effectively... the renderer still needs to be burned to the ground | ||
fluid.videoPlayer.languageMenu.produceTree = function (that) { | ||
// Silly damn renderer with its crazy JSON idiolect! | ||
that.model.languages = that.options.languages; | ||
var tree = { | ||
// create a menu item for each language in the model | ||
expander: { | ||
type: "fluid.renderer.repeat", | ||
repeatID: "language", | ||
controlledBy: "languages", | ||
controlledBy: "languageList", | ||
pathAs: "lang", | ||
tree: { | ||
value: "${{lang}.label}", | ||
|
@@ -216,6 +214,12 @@ var fluid_1_5 = fluid_1_5 || {}; | |
fluid.videoPlayer.languageMenu.bindEventListeners(that); | ||
fluid.videoPlayer.languageMenu.setUpKeyboardA11y(that); | ||
|
||
that.events.onLanguageListUpdated.addListener(function () { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be defined in defaults rather than in final init function. |
||
that.refreshView(); | ||
fluid.videoPlayer.languageMenu.bindEventListeners(that); | ||
fluid.videoPlayer.languageMenu.setUpKeyboardA11y(that); | ||
}); | ||
|
||
that.container.attr("role", "menu"); | ||
that.container.css("z-index", 9999); | ||
that.hideMenu(); | ||
|
@@ -243,6 +247,10 @@ var fluid_1_5 = fluid_1_5 || {}; | |
onReady: null, | ||
onRenderingComplete: null, | ||
onControlledElementReady: null, | ||
onLanguageListUpdated: null, | ||
// private event for testing | ||
afterMenuRender: null, | ||
|
||
afterFetchResources: null | ||
}, | ||
listeners: { | ||
|
@@ -251,7 +259,6 @@ var fluid_1_5 = fluid_1_5 || {}; | |
priority: "last" | ||
} | ||
}, | ||
languages: [], | ||
currentLanguagePath: "", | ||
showHidePath: "", | ||
strings: { | ||
|
@@ -286,13 +293,13 @@ var fluid_1_5 = fluid_1_5 || {}; | |
container: "{languageControls}.dom.menu", | ||
options: { | ||
model: "{languageControls}.model", | ||
languages: "{languageControls}.options.languages", | ||
applier: "{languageControls}.applier", | ||
showHidePath: "{languageControls}.options.showHidePath", | ||
currentLanguagePath: "{languageControls}.options.currentLanguagePath", | ||
strings: "{languageControls}.options.strings", | ||
events: { | ||
onControlledElementReady: "{languageControls}.events.onControlledElementReady" | ||
onControlledElementReady: "{languageControls}.events.onControlledElementReady", | ||
onLanguageListUpdated: "{languageControls}.events.onLanguageListUpdated" | ||
} | ||
} | ||
}, | ||
|
@@ -394,7 +401,8 @@ var fluid_1_5 = fluid_1_5 || {}; | |
fluid.defaults("fluid.videoPlayer.languageControls.eventBinder", { | ||
gradeNames: ["fluid.eventedComponent", "autoInit"], | ||
listeners: { | ||
"{button}.events.onPress": "{menu}.toggleView" | ||
"{button}.events.onPress": "{menu}.toggleView", | ||
"{menu}.events.afterRender": "{languageControls}.events.afterMenuRender.fire" | ||
} | ||
}); | ||
})(jQuery, fluid_1_5); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
/* | ||
Copyright 2012 OCAD University | ||
|
||
Licensed under the Educational Community License (ECL), Version 2.0 or the New | ||
BSD license. You may not use this file except in compliance with one these | ||
Licenses. | ||
|
||
You may obtain a copy of the ECL 2.0 License and BSD License at | ||
https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt | ||
*/ | ||
|
||
/*global jQuery, window, fluid*/ | ||
|
||
// JSLint options | ||
/*jslint white: true, funcinvoke: true, undef: true, newcap: true, nomen: true, regexp: true, bitwise: true, browser: true, forin: true, maxerr: 100, indent: 4 */ | ||
|
||
(function ($) { | ||
|
||
"use strict"; | ||
|
||
fluid.defaults("fluid.unisubComponent", { | ||
gradeNames: ["fluid.eventedComponent", "fluid.modelComponent", "autoInit"], | ||
finalInitFunction: "fluid.unisubComponent.finalInit", | ||
preInitFunction: "fluid.unisubComponent.preInit", | ||
model: { | ||
languages: [] | ||
}, | ||
events: { | ||
onReady: null, | ||
modelReady: null, | ||
onVideo: null | ||
}, | ||
listeners: { | ||
onVideo: "{fluid.unisubComponent}.onVideoHandler" | ||
}, | ||
"api-key": "0c01f5ca0ec8d1dc4e9e0f320a4d1afb1a50273d", | ||
"api-password": "idrcunisub", | ||
"api-username": "idrc", | ||
urls: { | ||
//api: "https://www.universalsubtitles.org/api2/partners/videos", | ||
apiLanguages: "http://www.universalsubtitles.org/api/1.0/subtitles/languages/", | ||
apiVideo: "http://www.universalsubtitles.org/api/1.0/video/", | ||
video: null | ||
}, | ||
hrefTemplate: "http://www.universalsubtitles.org/en/videos/g2QoNQgjJd5y/%lang/%subtitleId/", | ||
queryAmaraForCaptions: true | ||
}); | ||
|
||
fluid.unisubComponent.preInit = function (that) { | ||
that.languageList = []; | ||
that.videoCount = 0; | ||
that.onVideoHandler = function (options) { | ||
$.ajax({ | ||
dataType: "jsonp", | ||
url: options.url | ||
}).done(function (data) { | ||
// that.languageList = that.languageList.concat(data); | ||
|
||
fluid.each(data, function (capSpec, index) { | ||
that.languageList = that.languageList.concat({ | ||
// BROKEN: this is the wrong url: this is the url to the actual subtitles, | ||
// but the video player just needs the right url to the video itself | ||
src: fluid.stringTemplate(that.options.hrefTemplate, { | ||
lang: capSpec.code, | ||
subtitleId: capSpec.id | ||
}), | ||
type: "text/amarajson", | ||
srclang: capSpec.code, | ||
label: capSpec.name | ||
}); | ||
}); | ||
|
||
if (--that.videoCount <= 0) { | ||
that.applier.requestChange("languages", that.languageList); | ||
that.events.modelReady.fire(that.languageList); | ||
that.events.onReady.fire(that); | ||
} | ||
}); | ||
}; | ||
|
||
that.loadVideoMetaData = function (options) { | ||
$.ajax({ | ||
dataType: "jsonp", | ||
url: options.url | ||
}).done(function (data) { | ||
that.applier.requestChange("video", data); | ||
that.events.onVideo.fire({ | ||
url: that.buildUrl(that.options.urls.apiLanguages, { | ||
video_url: data.video_url | ||
}) | ||
}); | ||
}); | ||
}; | ||
|
||
that.buildUrl = function (baseURL, params) { | ||
return [baseURL, "?", $.param(params)].join(""); | ||
}; | ||
}; | ||
|
||
fluid.unisubComponent.finalInit = function (that) { | ||
if (!that.options.queryAmaraForCaptions || !that.options.urls.video) { | ||
return; | ||
} | ||
|
||
var videoUrlsArray = []; | ||
if (typeof that.options.urls.video[0] === "string") { | ||
videoUrlsArray = fluid.makeArray(that.options.urls.video); | ||
} else { | ||
fluid.each(that.options.urls.video, function (vid, index) { | ||
videoUrlsArray[index] = vid.src; | ||
}); | ||
} | ||
|
||
that.videoCount = videoUrlsArray.length; | ||
fluid.each(videoUrlsArray, function (vidUrl, index) { | ||
if (vidUrl.substr(0, 7) === "http://") { | ||
that.loadVideoMetaData({ | ||
url: that.buildUrl(that.options.urls.apiVideo, { | ||
username: that.options["api-username"], | ||
password: that.options["api-password"], | ||
video_url: vidUrl | ||
}) | ||
}); | ||
} else { | ||
that.videoCount--; | ||
} | ||
}); | ||
if (that.videoCount <= 0) { | ||
that.events.modelReady.fire(that.languageList); | ||
that.events.onReady.fire(that); | ||
} | ||
}; | ||
|
||
})(jQuery); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -165,7 +165,9 @@ var fluid_1_5 = fluid_1_5 || {}; | |
onScrub: "{videoPlayer}.events.onScrub", | ||
afterScrub: "{videoPlayer}.events.afterScrub", | ||
onTranscriptsReady: "{videoPlayer}.events.canBindTranscriptMenu", | ||
onCaptionsReady: "{videoPlayer}.events.canBindCaptionMenu" | ||
onCaptionsReady: "{videoPlayer}.events.canBindCaptionMenu", | ||
onCaptionControlsRendered: "{videoPlayer}.events.onCaptionControlsRendered", | ||
onCaptionListUpdated: "{videoPlayer}.events.onCaptionListUpdated" | ||
}, | ||
listeners: { | ||
onReady: "{videoPlayer}.events.onControllersReady" | ||
|
@@ -179,6 +181,19 @@ var fluid_1_5 = fluid_1_5 || {}; | |
type: "fluid.videoPlayer.captionator", | ||
container: "{videoPlayer}.dom.videoPlayer", | ||
createOnEvent: "onMediaReady" | ||
}, | ||
amara: { | ||
type: "fluid.unisubComponent", | ||
createOnEvent: "onReady", | ||
options: { | ||
urls: { | ||
video: "{videoPlayer}.options.video.sources" | ||
}, | ||
events: { | ||
modelReady: "{videoPlayer}.events.onAmaraCaptionsReady" | ||
}, | ||
queryAmaraForCaptions: "{videoPlayer}.options.queryAmaraForCaptions" | ||
} | ||
} | ||
}, | ||
preInitFunction: "fluid.videoPlayer.preInit", | ||
|
@@ -209,6 +224,19 @@ var fluid_1_5 = fluid_1_5 || {}; | |
args: ["{videoPlayer}"] | ||
}, | ||
|
||
onCaptionListUpdated: null, | ||
onAmaraCaptionsReady: null, | ||
onAmaraCaptionsReadyBoiled: { | ||
event: "onAmaraCaptionsReady", | ||
args: ["{videoPlayer}", "{arguments}.0"] | ||
}, | ||
// private events used for testing | ||
onCaptionControlsRendered: null, | ||
onCaptionControlsRenderedBoiled: { | ||
event: "onCaptionControlsRendered", | ||
args: ["{videoPlayer}", "{arguments}.0"] | ||
}, | ||
|
||
// public, time events | ||
onTimeUpdate: null, | ||
|
||
|
@@ -281,7 +309,8 @@ var fluid_1_5 = fluid_1_5 || {}; | |
volume: 60, | ||
muted: false, | ||
canPlay: false, | ||
play: false | ||
play: false, | ||
languageList: [] | ||
}, | ||
templates: { | ||
videoPlayer: { | ||
|
@@ -290,6 +319,7 @@ var fluid_1_5 = fluid_1_5 || {}; | |
} | ||
}, | ||
videoTitle: "unnamed video", | ||
queryAmaraForCaptions: true, | ||
invokers: { | ||
showControllers: "fluid.videoPlayer.showControllers", | ||
hideControllers: "fluid.videoPlayer.hideControllers" | ||
|
@@ -465,6 +495,8 @@ var fluid_1_5 = fluid_1_5 || {}; | |
that.toggleFullscreen = function () { | ||
that.applier.requestChange("fullscreen", !that.model.fullscreen); | ||
}; | ||
|
||
that.model.languageList = that.options.video.captions; | ||
}; | ||
|
||
fluid.videoPlayer.postInit = function (that) { | ||
|
@@ -503,6 +535,30 @@ var fluid_1_5 = fluid_1_5 || {}; | |
fluid.videoPlayer.finalInit = function (that) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This final init function should only contain model/applier binding material. Everything else should be moved out into onCreate or onAttach. The fetchResources call should result in an event firing and the callback should be registered through the defaults and bind to a global function. |
||
that.container.attr("role", "application"); | ||
|
||
that.applier.modelChanged.addListener("languageList", function (newModel, oldModel, requestSpec) { | ||
that.events.onCaptionListUpdated.fire(); | ||
}); | ||
that.events.onAmaraCaptionsReadyBoiled.addListener(function (that, captionData) { | ||
|
||
/* | ||
var capList = fluid.copy(that.model.languageList); | ||
fluid.each(captionData, function (cap, index) { | ||
var lang = fluid.copy(cap); | ||
capList.push({ | ||
href: fluid.stringTemplate("http://www.universalsubtitles.org/en/videos/g2QoNQgjJd5y/%lang/%subtitleId/", { | ||
lang: cap.code, | ||
subtitleId: cap.id | ||
}), | ||
type: "text/amarajson", | ||
srclang: cap.code, | ||
label: cap.name | ||
}); | ||
}); | ||
*/ | ||
var capList = fluid.copy(that.model.languageList).concat(captionData); | ||
that.applier.requestChange("languageList", capList); | ||
}); | ||
|
||
// Render each media source with its custom renderer, registered by type. | ||
// If we aren't on an HTML 5 video-enabled browser, don't bother setting up the controller, captions or transcripts. | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most if not all contents of this final init function should be eliminated. We can use default component events such as onCreate or onAttach to finish up initialization.