emadalam / atvjs Goto Github PK
View Code? Open in Web Editor NEWBlazing fast Apple TV application development using pure JavaScript
Home Page: https://emadalam.github.io/atvjs
License: MIT License
Blazing fast Apple TV application development using pure JavaScript
Home Page: https://emadalam.github.io/atvjs
License: MIT License
Hi – great library, helped us a lot in setting up our tvOS app. But I believe I've come across a bug with the handling of error pages. The logic to detect whether to replace or push a document to the navigation stack is this, within the cleanNavigate method:
if (!replace && (!last || last !== loaderDoc || last !== errorDoc)) {
If the last doc was an errorDoc this returns true...as the last doc wasn't a loader doc. Therefore I believe it should be this:
if (!replace && (!last || ( last !== loaderDoc && last !== errorDoc ))) {
This will correctly fathom if the last doc was either an error or a loader, return false and proceed to replace the doc and not push.
If you are happy with this change I'll create a PR
Hello,
I would like to pass options to a page with data-href-page-options
.
<button data-href-page="details-page" data-href-page-options='{"title": "Hello World"}'>
/details-page/index.js :
ATV.Page.create({
name: 'DetailsPage',
template: template,
WHAT CODE TO RETRIEVE OPTIONS ?
});
/details-page/template.hbs :
<document>
<productTemplate>
<banner>
<stack>
<title>WHAT CODE TO DISPLAY OPTIONS</title>
</stack>
</banner>
</productTemplate>
</document>
Thanks.
docs
folder setup for entire documentationgh-pages
to docs
setup https://github.com/blog/2228-simpler-github-pages-publishingApple introduced Prototypes and needsMore event handling for performance in TVOS 9. Can this be added as a new feature.
When using Menu Pages like the boilerplate, how can I handle deeplinking from the app Top Shelf?
I'd like to check if the "options" parameter of onLaunch has the "DEEPLINK" property and load the movies page directly without loading the Home page.
Would it possible to add a header when fetching images?
My app requires authorisation for downloading user images, this can be done by adding a Authorization header with the bearer token to the request.
I have a page which generated depend on the storage via page ready method:
ready(options, resolve, reject) {
var history = ATV.Settings.get('history');
...
}
and I set the option reloadOnSelect for this page in menu:
menu: {
items: [{
id: 'home',
name: 'My TV',
page: HomePage,
attributes: { autoHighlight: true,
reloadOnSelect: true
}
},
}
While I update storage in other page and navigate back the home page, the page can not be updated. Looking to the debug console, the ready is not been called. So will reloadOnSelect invoke ready() to be called every time even the page already in the stack ? Anyway to update the content in the stack ? I have read you suggestion to use pubsub-js, any sample code for that ?
Thanks for help.
hong
Can't change background color or background image in application.
Hey.
First, thanks for your work. I think, that this project can be very useful, but I got the following problem.
I've created an index.js file with the following content, based on your example code.
var ATV = require('atvjs');
ATV.Page.create({
name: 'home',
// use a template function from your favourite templating engine
// or pass a raw template function
template(data) {
return `<document>
<alertTemplate>
<title>${data.title}</title>
<description>${data.description}</description>
</alertTemplate>
</document>`;
},
// pass some raw data to be applied
// or a data function that returns the data
data: {
title: 'Homepage',
description: 'This is my super awesome homepage created using atvjs.'
}
});
// later in your application you can do something like below to navigate to the page
ATV.Navigation.navigate('home');
I'm using Node.js 4.4.0. And the following error ist the result of that.
/srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:18710
var parser = new DOMParser(); // native DOM parser
^
ReferenceError: DOMParser is not defined
at Object._typeof (/srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:18710:19)
at __webpack_require__ (/srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:34:30)
at Object.<anonymous> (/srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:77:16)
at __webpack_require__ (/srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:34:30)
at /srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:54:18
at /srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:57:10
at webpackUniversalModuleDefinition (/srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:7:20)
at Object.<anonymous> (/srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:14:3)
at Module._compile (module.js:435:26)
at Object.Module._extensions..js (module.js:442:10)
Do you have any idea how this can be fixed?
Thanks.
The commonly used methods are under a second level object.
Create aliases
ATV.Page.create
--> ATV.createPage
ATV.Menu.create
--> ATV.createMenu
ATV.Navigation.navigate
--> ATV.navigateTo
ATV.Navigation.navigateToMenuPage
--> ATV.navigateToMenuPage
ATV.Navigation.presentModal
--> ATV.presentModal
ATV.Navigation.dismissModal
--> ATV.dismissModal
Now that the AppleTV platform is stable enough, it would make sense to get rid of the redundant dependencies and rely on ES6 or related resolutions. Read #15 (comment) and #15 (comment).
babel-polyfill
Promise
alternativeslodash
(use custom stripped down build if required)pubsub-js
Modal dialogs created with navigationDocument.presentModal()
are able to be dismissed but using Navigation.showError()
results in a dialog where the button does not work, escape or home must be used to dismiss.
Consider the following code if added to the Movie Catalog example app in the ready
method of the HomePage
object:
const showError = () => {
// const alert = `<?xml version="1.0" encoding="UTF-8" ?>
// <document>
// <alertTemplate>
// <title>Error</title>
// <description>This modal cannot be dismissed.</description>
// <button data-alert-dissmiss="close">
// <text>OK</text>
// </button>
// </alertTemplate>
// </document>`;
// const error = ATV.Navigation.showError({ template: alert, style: '' });
const alert = `<?xml version="1.0" encoding="UTF-8" ?>
<document>
<alertTemplate>
<title>Error</title>
<description>This modal can be dismissed.</description>
<button>
<text>OK</text>
</button>
</alertTemplate>
</document>`;
const parser = new DOMParser();
const error = parser.parseFromString(alert, 'application/xml');
navigationDocument.presentModal(error);
error.addEventListener('select', () => {
ATV.Navigation.dismissModal();
})
};
The uncommented version works as expected. Inverting the commented code results in the modal not being dismissed but with the data-alert-dissmiss
[sic] attribute the navigationDocument.dismissModal()
method is called, as indicated by the log:
close button clicked within the modal, dismissing modal...
var amc = ATV.Page.create({name: 'amc', ...... });
var allVideos = ATV.Page.create({name: 'allVideos', ...... });
var menu = ATV.Menu.create({
// any attributes that you want to set on the root level menuBar element of TVML
attributes: {},
// array of menu item configurations
items: [{
id: 'amc',
name: 'AMC',
page: amc
}, {
id: 'allVideos',
name: 'All Videos',
page: allVideos,
attributes: {
autoHighlight: true // auto highlight on navigate
}
}]
});
When I run ATV.Navigation.navigateToMenuPage();
I get [Warning] No menu configuration exists, cannot navigate to the menu page.
This seems to work when its inside ATV.start
I'm trying to build this app that uses a third party library to access an API and thus does not use the Ajax component of atvjs.
When I use ATV.start() and pass to it the loadingTpl, it will show the loading indicator when I change page from the menubar, however even though by ready() method does call resolve(), the loading indicator is still being displayed.
How can I hide it?
Just wondering if we could get a small example project here thats just a menu
-> catalog
-> video play
without all the dependencies of https://github.com/emadalam/tvml-catalog-using-atvjs . That project is awesome but for a small project, it requires karma, webpack, gulp, babel etc, which seems a bit overkill.
Using a listTemplate
, I would like to make the relatedContent
area dynamic, populating it with content when a listItemLockup
is highlight
ed by the user.
Consider the following (simplified) page:
import ATV from 'atvjs';
import template from './template.hbs';
const APIURL = 'http://myapi/shows';
let Page = ATV.Page.create({
name: 'shows',
template: template,
events: {
select(e) {
console.log(e);
},
highlight(e) {
// RE-RENDER
}
},
ready(options, resolve, reject) {
ATV.Ajax
.get(APIURL)
.then((xhr) => {
let response = xhr.response;
resolve(response);
}, (xhr) => {
let response = xhr.response;
reject({
status: xhr.status,
message: response.message
});
});
}
});
export default Page;
Using the ReactJS model as an analogy, I would like to be able to do something like:
select
event, derive data from event
object to create "related content".I tried to do this by storing a reference to the resolve
method passed into ready
and giving that fresh data but, although I can see output in the console that this has done something with the data, the page doesn't re-render.
I'm assuming this is possible somehow, I'm probably missing something really obvious...
EDIT:
Having played around, it seems you can do some old-fashioned DOM traversal/manipulation using the reference to doc
that the afterReady
method receives. Although this is a passable way of doing things, I would be interested to know if there scope for something more aligned with the way modern SPA's are built, rather than hunting down nodes and injecting content in to them.
@emadalam this isn't an issue so much as a question - How would you go about refreshing the UI when you need new data to populate? For example, if you have a movie listing page, periodically the list of movies changes. I'd like to cause the UI to refresh periodically. Thanks in advance 😄
I find it confusing and limiting when the Ajax call returns a promise but doesn't utilize the reject capability.
So instead of handling success/failure in the resolved promise (the then()
):
ATV
.Ajax
.post('someURL', {data: data})
.then((xhr) => {
// xhr succeeded
}, (xhr) => {
// xhr failed
});
You would have more true promise-based logic using then()
and/or catch()
and/or finally()
:
ATV
.Ajax
.post('someURL', {data: data})
.then((xhr) => {
// xhr succeeded
})
.catch((xhr) => {
// xhr failed
})
.finally(() => {
// regardless of success/failure, also do this
});
For developers who understand promises, the current implementation seems halfway done. It also prevents normal promise chaining, which flattens out the old "callback hell" problem.
Hello. Could you please provide a sample code for initializing the player and playing the actual movie.
Thank you.
I want when I click on a thumbnail in the catalogue view to the product view to play the video of the thumbnail.
I get thumbnail and video from a json file.
and this is my catalog index.js file:
let Page = ATV.Page.create({
name: 'catalog',
url: 'http://localhost:9001/assets/data/video.json',
template: template,
events: {
select: 'onSelect'
},
onSelect(e) {
ATV.Navigation.navigate('product');
}
});
And I don't know how I can play the video when I get to the product(video) view.
I'm actually writing a private TVML/TVJS-App with atvjs.
First thanks for your brilliant framework-work!
I've got one problem:
I've got an interactive HomePage and also interactive subpages.
So at the start of the app the app gets the JSON from the server and render it to the template.
This page is cached then and can not be re-rendered; or?
For example:
I've got a page with a list of TV-Show episodes, on these episodes I've got a marker for the "Last seen"-episode. When I watch an episode the JS-File of the player then tells the server that the episode is watched. After exiting the player, the list should be dynamically re-rendered to display the newest server-information.
Is there a way to make boundings between ajax/template to re-render pages dynamically?
Thanks a lot!
When ATV.Navigation.presentModal(descriptiveAlertTemplateString) is called the modal opens, but on the first time it closes itself right away. It seems fine on the calls after that. Might this be a bug?
Hello,
I would like to fetch json and display it on template.
I use :
ATV.Page.create({
name: 'home',
url: 'http://www.example.com/data.json',
template: template
});
data.json :
{
"CATALOG": {
"ITEM": [{
"TITLE": "Title 1"
}, {
"TITLE": "Title 2"
}, {
"TITLE": "Title 3"
}]
}
}
in template.hbs, I use :
... <title>{{ CATALOG.ITEM[0].TITLE }}</title> ...
But I have error launching application.
How do I do to get the first title ?
Is there any way of debugging the JS? Even console.log
doesn't seem to do anything.
Came across this comment on SO indicating that pages would regenerate when you navigate to them.
This doesn't seem to be the case for me at the moment, are changes to the template supposed to be available without rebooting the application?
Any thoughts on how to best implement "automatically play next", when at the end of one episode, the player will automatically pick up the next one?
Selecting the menu item loads the previously loaded cached page and there is no way to force reload it based on configuration.
Support attribute configuration reloadOnSelect
to load a non-cached version of the page on every selection.
...
menu: {
items: [{
...
attributes: {
reloadOnSelect: true
}
}]
}
...
If you define more than one event listener in the events
object, the application will crash when it displays that page. I've confirmed this by adding two events to various pages in the example app, for example:
import ATV from 'atvjs';
import template from './template.hbs';
let Page = ATV.Page.create({
name: 'list-with-banner',
template: template,
events: {
highlight: 'onHighlight',
select: 'onSelect'
},
onSelect(e) {
console.log(e);
},
onHighlight(e) {
console.log(e);
}
});
export default Page;
This is the error in Safari's console: There was an error in the page code. TypeError: self type check failed for Objective-C instance method
I've tried various ways of declaring the event config/handlers but the result is always the same (sometimes a different error message, however).
From one of the PRs #12
This allows to build URLs for pages dynamically based on the options.urlParams that are handed over to the page.
Uses the same node-module that express uses, so the very same syntax applies. For example use “http://httpbin.org/get?test=:test” with options = {urlParams: {test: true}} to get “http://httpbin.org/get?test=true”.
path-to-regexp
Handy code snippet
function toQueryString(obj) {
return (
_.map(obj, (v, k) => {
if (_.isArray(v)) {
return (_.map(v, (av) => `${k}[]=${av}`)).join('&');
} else {
return `${encodeURIComponent(k)}=${encodeURIComponent(v)}`;
}
})
).join('&');
}
function toUrl(url = '', params = {}) {
let q = toQueryString(params);
let urlBuffer = [url];
if (q) {
urlBuffer.push(/\?.+$/.test(url) ? `&${q}` : `?${q}`);
}
return urlBuffer.join('');
}
I have an app that uses a MenuBar template with items set with reloadOnSelect.
Every time I change view it reloads the content from an API and the loading indicator shows up. Each view has a dark theme but when the loading indicator shows, the background is bright.
Is it possible to set a dark background when the loader shows?
I thought of setting a class to the element and use CSS but it does not work either.
I am trying to develop an application using atvjs; installed node and npm; installed packages and so on. If in my app.js I do "import atvjs" is not working; also if I do "var atvjs = require('atvjs') is not working and I get "ReferenceError: Can't find variable: require"
Where am I wrong?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.