Understanding TVJS - Player

I'm an experienced iOS Developer, trying to get a feel for tvOS. I've set up the AppDelegate and created the necessary components, and tried to get a few images up in a Catalog Template. I have very little knowledge of JavaScript (only had like 10 hours of experience trying to get something running), so I'm trying to figure something out just by matching the patterns presented by the few official documentation available. I know you can use storyboards and regular UIKit practices to generate layouts, but I need to understand these templates at least at a basic level. I want to take some time running through some of my files - in hopes of getting some feedback from you guys. I'll focus on the client files.


application.js

//treating this as a black box. Feed it a URL to the tvml file, and you'll get a doc you can push to the screen
function getDocument(url) {
  var templateXHR = new XMLHttpRequest();
  templateXHR.responseType = "document";
  templateXHR.addEventListener("load", function() {pushDoc(templateXHR.responseXML);}, false);
  templateXHR.open("GET", url, true);
  templateXHR.send();
  return templateXHR;
}

//pushes the document to the screen. Analogous to navigationController.pushViewController
function pushDoc(document) {
  navigationDocument.pushDocument(document);
}

//entry point for tvOS application - at start we want to push the first screen we want our users to encounter
App.onLaunch = function(options) {
  var templateURL = 'http://localhost:9001/templates/catalogTemplate.tvml';
  getDocument(templateURL);
}

//self explanatory
App.onExit = function() {
  console.log('App finished');
}


catalogTemplate.tvml

<document>
  <catalogTemplate>
  <banner>
  <title>Title of thingy</title>
  </banner>
  <list>
  <section>
  <header>
  <title>Section Header</title>
  </header>
  <listItemLockup>
  <title>Inspiration Videos</title>
  <decorationLabel>6</decorationLabel>
  <relatedContent>
  <grid>
  <section>
  <lockup>
  <img src="http://localhost:9001/images/photo.png" width="308" height="308" />
  </lockup>
  </section>
  </grid>
  </relatedContent>
  </listItemLockup>
  </section>
  </list>
  </catalogTemplate>
</document>


I've got a nice default interface going, with a single cell with a photo displayed. But what I really want to do is to be able to select the cell, and display a video for users the watch. For cell selection, I understand that I need to use addEventListener. The TVMLCatalogUsingTemplates sample code shows a flexible way of doing this via the following statement:


//in application.js - evaluateScripts

//addEventListener is similar to @IBAction. "select" denotes to listen to selection, but I'm not sure what 'bind' does,
//and why presenter is passed into the argument. I could use a explanation on the role of the 2nd argument
doc.addEventListener("select", Presenter.load.bind(Presenter));



//in Presenter.js
//event is a parameter passed in from the above addEventListener method call. event = Presenter in this case?

  load: function(event) {
    var self = this, //not sure
        ele = event.target, //assuming Presenter is the event, what is target?
        templateURL = ele.getAttribute("template"),
        presentation = ele.getAttribute("presentation");
    if (templateURL) {
      self.showLoadingIndicator(presentation);
      resourceLoader.loadResource(templateURL,
        function(resource) {
          if (resource) {
            var doc = self.makeDocument(resource);
       
            doc.addEventListener("select", self.load.bind(self));
            doc.addEventListener("highlight", self.load.bind(self));


            if (self[presentation] instanceof Function) {
              self[presentation].call(self, doc, ele);
            } else {
              self.defaultPresenter.call(self, doc);
            }
          }
        }
      );
    }
  },


For someone who's almost clueless in JavaScript and DOMS, I'm having trouble interpreting the ideas presented here. Been studying the demo for 15 hours already, and I've hit a steep wall due to JavaScript blindness. Instead of using the TVMLCatalogUsingTemplates way of handling listeners, can someone offer a much more simple way to do it? Even at the expense of flexibility.



Next, after being able to select cells, I'd like to segue to a video. I want create the video streaming experience via the catalog Template. I know the TVJSframework has a Player class specifically for this, but I'm having trouble understanding how to initialize this class in JavaScript and make use of it. For quick reference, here's the link to the class documentation:

https://developer.apple.com/library/prerelease/tvos/documentation/TVMLJS/Reference/TVJSPlayer_Ref/index.html#//apple_ref/javascript/cl/Player


Thanks in advance!

Accepted Reply

For general JavaScript API reference this Web site is invaluable:

https://developer.mozilla.org/en-US/docs/Web/API


This is a great reference specifically for event listeners:

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener?redirectlocale=en-US&redirectslug=DOM%2FEventTarget.addEventListener


To answer some of your specific questions:


doc.addEventListener("select", Presenter.load.bind(Presenter));

The second argument is the Object/Function that will handle the select event. The bind function sets the scope for the event handler when called.


load: function(event)

The event object here, has information regarding the event, and the element where the event was initiated from.


I highly recommend learning how to work with event listeners, however you are also able to add onselect and onplay attributes to individual elements.


Here is a short example to start playback:

var player = new Player();
player.playlist = new Playlist();

var mediaitem = new MediaItem('video', "MediaItem URL");
player.playlist.push(mediaitem)

player.play()

Replies

For general JavaScript API reference this Web site is invaluable:

https://developer.mozilla.org/en-US/docs/Web/API


This is a great reference specifically for event listeners:

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener?redirectlocale=en-US&redirectslug=DOM%2FEventTarget.addEventListener


To answer some of your specific questions:


doc.addEventListener("select", Presenter.load.bind(Presenter));

The second argument is the Object/Function that will handle the select event. The bind function sets the scope for the event handler when called.


load: function(event)

The event object here, has information regarding the event, and the element where the event was initiated from.


I highly recommend learning how to work with event listeners, however you are also able to add onselect and onplay attributes to individual elements.


Here is a short example to start playback:

var player = new Player();
player.playlist = new Playlist();

var mediaitem = new MediaItem('video', "MediaItem URL");
player.playlist.push(mediaitem)

player.play()

Have you seen this thread?


Also this StackOverflow question should help, don't use python for videos as they won't play.

This is what worked for me:


load: function(event) {

console.log(event);

var self = this,

ele = event.target,

videoURL = ele.getAttribute("videoURL"),

templateURL = ele.getAttribute("template"),

presentation = ele.getAttribute("presentation");

if (videoURL && (event.type == "select")) {

self.launchPlayer(videoURL);

} else if (templateURL) {


... and then adding


removeLoadingIndicator: function() {

if (this.loadingIndicatorVisible) {

navigationDocument.removeDocument(this.loadingIndicator);

this.loadingIndicatorVisible = false;

}},

launchPlayer: function launchPlayer(videoURL) {

var player = new Player();

var playlist = new Playlist();

var mediaItem = new MediaItem("video", videoURL);

player.playlist = playlist;

player.playlist.push(mediaItem);

player.present();

},

If you want a segue effect, you will have to push more videos to the end of the

media items playlist. Like..


player.playlist.push(mediaitem1)

player.playlist.push(mediaitem2)

player.playlist.push(mediaitem3)

player.playlist.push(mediaitem4)


then have the player play.