├── .gitignore ├── .gitmodules ├── README.md ├── assets ├── carousel.png ├── main.png └── playback.png ├── index.js ├── package.json ├── static ├── img │ ├── bbc_background_540.png │ ├── bbc_background_720.png │ └── fruit │ │ ├── apple.png │ │ ├── banana.png │ │ ├── grapes.png │ │ ├── orange.png │ │ ├── peach.png │ │ └── pear.png ├── mp4 │ └── spinning-logo.mp4 ├── script │ └── appui │ │ ├── components │ │ ├── carouselcomponent.js │ │ ├── horizontalprogresscomponent.js │ │ ├── simple.js │ │ └── simplevideocomponent.js │ │ ├── datasources │ │ └── simplefeed.js │ │ ├── formatters │ │ └── simpleformatter.js │ │ ├── layouts │ │ ├── 1080p.js │ │ ├── 540p.js │ │ └── 720p.js │ │ └── sampleapp.js └── style │ ├── base.css │ └── layouts │ ├── 1080p.css │ ├── 540p.css │ └── 720p.css └── views ├── error.mustache ├── imports.mustache └── index.mustache /.gitignore: -------------------------------------------------------------------------------- 1 | /.project 2 | node_modules 3 | **/*.DS_Store 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "antie"] 2 | path = antie 3 | url = https://github.com/bbc/tal.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Example TAL Application 2 | ![maintenance-status](https://img.shields.io/badge/maintenance-deprecated-red.svg) 3 | [![No Maintenance Intended](http://unmaintained.tech/badge.svg)](http://unmaintained.tech/) 4 | 5 | An example TV application using the [TAL](https://www.github.com/bbc/tal) framework from the BBC. 6 | 7 | ## TAL Replacement update 28/09/2023 8 | 9 | We are working towards an approach of modular packages focused on specific features such as playback, navigation, and device abstraction. We do not intend to provide a UI framework, and these packages should work with a number of front-end frameworks. As part of this work, we are in the process of making internal TV packages open source. Some of these have been released already including: 10 | 11 | - [Bigscreen Player](https://github.com/bbc/bigscreen-player) 12 | - [LRUD Spatial](https://github.com/bbc/lrud-spatial) 13 | - [Melanite](https://github.com/bbc/melanite) 14 | 15 | Looking further to the future, we are developing an open source demo app, including associated documentation. This will enable the wider community to understand how these packages work together to build a TV application. 16 | 17 | ## Contact us at BBC TV Open Source 20/03/2023 18 | 19 | We have now created a mailbox where you can [contact us](mailto:tvopensource@bbc.co.uk) with any questions related to TAL or the 20 | future of this project. We aim to respond to emails within a week. We hope to share some details of the replacement to TAL soon. 21 | 22 | # Deprecation Announcement 09/01/2023 23 | 24 | On 12/12/2022 we announced the deprecation of [TAL](https://github.com/bbc/tal/), on which this repository is based. 25 | This will allow us to concentrate on future work, which we hope to share details of soon. 26 | 27 | We apologise that we were not active in keeping the TAL community up to date with the status of these 28 | projects. Going forward, we will provide regular updates on the future of TAL. 29 | 30 | As part of the deprecation, pull requests will be disabled and outstanding issues will be closed. 31 | TAL and this example repository will not be actively maintained. 32 | 33 | We will answer any questions found in the issues backlog as best we can. There will soon be a email address you 34 | can use to contact us. This readme will be updated when this becomes available. 35 | 36 | --- 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | # Getting Started 47 | 48 | ``` 49 | git clone git@github.com:bbc/talexample.git 50 | cd talexample 51 | npm install 52 | npm start 53 | ``` 54 | 55 | Visit http://localhost:1337 in your browser. Use the UP, DOWN, LEFT, RIGHT keys to navigate, use ENTER/RETURN to select. 56 | 57 | # More Information 58 | 59 | See [github.com/bbc/tal](https://www.github.com/bbc/tal) or [bbc.github.io/tal](http://bbc.github.io/tal/getting-started/introducing-tal.html) for documentation. 60 | -------------------------------------------------------------------------------- /assets/carousel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/talexample/34d0b343caa2588ee8b1c7e9408b87be365f1a7c/assets/carousel.png -------------------------------------------------------------------------------- /assets/main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/talexample/34d0b343caa2588ee8b1c7e9408b87be365f1a7c/assets/main.png -------------------------------------------------------------------------------- /assets/playback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/talexample/34d0b343caa2588ee8b1c7e9408b87be365f1a7c/assets/playback.png -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * The entry point for TAL based applications using node.js 3 | * 4 | * @copyright Copyright (c) 2013 British Broadcasting Corporation 5 | * (http://www.bbc.co.uk) and TAL Contributors (1) 6 | * 7 | * (1) TAL Contributors are listed in the AUTHORS file and at 8 | * https://github.com/bbc/TAL/AUTHORS - please extend this file, 9 | * not this notice. 10 | * 11 | * @license Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | * 23 | * All rights reserved 24 | * Please contact us for an alternative licence 25 | */ 26 | 27 | var express = require('express'); 28 | var app = express(); 29 | var AntieFramework = require('tal'); 30 | var mustacheExpress = require('mustache-express'); 31 | 32 | // Setup mustache for view templating 33 | app.engine('mustache', mustacheExpress()); 34 | app.set('view engine', 'mustache'); 35 | app.set('views', __dirname + '/views'); 36 | 37 | app.get('/', function (req, res) { 38 | 39 | // Path to device configuration directory 40 | var configPath = "node_modules/tal/config"; 41 | var antie = new AntieFramework(configPath); 42 | 43 | // Get normalised brand and model from url parameters 44 | var device_brand = antie.normaliseKeyNames(req.query.brand || "default"); 45 | var device_model = antie.normaliseKeyNames(req.query.model || "webkit"); 46 | 47 | // Load framework device config files, named BRAND-MODEL-default.json 48 | var device_configuration; 49 | 50 | try { 51 | device_configuration = antie.getConfigurationFromFilesystem(device_brand + "-" + device_model + "-default", "/devices"); 52 | } catch(e) { 53 | res.status(406).render('error', { 54 | exception: e 55 | }); 56 | 57 | return; 58 | } 59 | 60 | // Substitute application_id wherever /%application%/ token is present in device configuration 61 | var application_id = "sampleapp"; 62 | device_configuration = device_configuration.replace(/%application%/g, application_id); 63 | 64 | var device_configuration_decoded = JSON.parse(device_configuration); 65 | 66 | res.render('index', { 67 | root_html_tag: antie.getRootHtmlTag(device_configuration_decoded), 68 | headers: antie.getDeviceHeaders(device_configuration_decoded), 69 | application_id: application_id, 70 | device_configuration: device_configuration, 71 | extra_body: antie.getDeviceBody(device_configuration_decoded) 72 | }); 73 | }); 74 | 75 | app.use('/tal', express.static('node_modules/tal')); 76 | app.use('/static', express.static('static')); 77 | 78 | app.listen(1337, function () { 79 | console.log('Example app listening on port 1337'); 80 | }); 81 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "talexample", 3 | "version": "0.2.0", 4 | "description": "Example application for the TAL framwork.", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "test": "echo \"Error: There are no tests for this example app\" && exit 1" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git://github.com/bbc/talexample.git" 13 | }, 14 | "keywords": [ 15 | "tal", 16 | "talframework", 17 | "bbc" 18 | ], 19 | "author": "BBC Future Media", 20 | "license": "Apache-2.0", 21 | "bugs": { 22 | "url": "https://github.com/bbc/talexample/issues" 23 | }, 24 | "dependencies": { 25 | "tal": "9.0.0", 26 | "express": "^4.13.4", 27 | "mustache-express": "^1.2.2" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /static/img/bbc_background_540.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/talexample/34d0b343caa2588ee8b1c7e9408b87be365f1a7c/static/img/bbc_background_540.png -------------------------------------------------------------------------------- /static/img/bbc_background_720.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/talexample/34d0b343caa2588ee8b1c7e9408b87be365f1a7c/static/img/bbc_background_720.png -------------------------------------------------------------------------------- /static/img/fruit/apple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/talexample/34d0b343caa2588ee8b1c7e9408b87be365f1a7c/static/img/fruit/apple.png -------------------------------------------------------------------------------- /static/img/fruit/banana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/talexample/34d0b343caa2588ee8b1c7e9408b87be365f1a7c/static/img/fruit/banana.png -------------------------------------------------------------------------------- /static/img/fruit/grapes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/talexample/34d0b343caa2588ee8b1c7e9408b87be365f1a7c/static/img/fruit/grapes.png -------------------------------------------------------------------------------- /static/img/fruit/orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/talexample/34d0b343caa2588ee8b1c7e9408b87be365f1a7c/static/img/fruit/orange.png -------------------------------------------------------------------------------- /static/img/fruit/peach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/talexample/34d0b343caa2588ee8b1c7e9408b87be365f1a7c/static/img/fruit/peach.png -------------------------------------------------------------------------------- /static/img/fruit/pear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/talexample/34d0b343caa2588ee8b1c7e9408b87be365f1a7c/static/img/fruit/pear.png -------------------------------------------------------------------------------- /static/mp4/spinning-logo.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/talexample/34d0b343caa2588ee8b1c7e9408b87be365f1a7c/static/mp4/spinning-logo.mp4 -------------------------------------------------------------------------------- /static/script/appui/components/carouselcomponent.js: -------------------------------------------------------------------------------- 1 | define( 2 | "sampleapp/appui/components/carouselcomponent", 3 | [ 4 | "antie/widgets/component", 5 | "antie/datasource", 6 | "antie/widgets/label", 7 | "antie/widgets/carousel", 8 | "antie/widgets/carousel/binder", 9 | "antie/widgets/carousel/keyhandlers/activatefirsthandler", 10 | "antie/widgets/carousel/strips/wrappingstrip", 11 | "antie/widgets/carousel/navigators/wrappingnavigator", 12 | "antie/widgets/carousel/strips/cullingstrip", 13 | "antie/widgets/carousel/strips/hidingstrip" 14 | ], 15 | function (Component, DataSource, Label, Carousel, Binder, ActivateFirstHandler, WrappingStrip, 16 | WrappingNavigator, CullingStrip, HidingStrip) { 17 | 'use strict'; 18 | 19 | function evtBind(self, functionName) { 20 | return function (evt) { 21 | self[functionName].call(self, evt); 22 | }; 23 | } 24 | 25 | return Component.extend({ 26 | init: function init () { 27 | init.base.call(this, 'carouselComponent'); 28 | 29 | this._addComponentListeners(); 30 | this._description = new Label(); 31 | this._description.addClass('description'); 32 | this.appendChildWidget(this._description); 33 | }, 34 | 35 | onBeforeShow: function (evt) { 36 | this._initialItem = evt.args.initialItem || 0; 37 | this._dontShowYet(evt); 38 | this.setDescription(evt.args.description || ""); 39 | this._createCarousel(evt.args); 40 | this.appendChildWidget(this._carousel); 41 | this._addCarouselListeners(); 42 | this._setCarouselAlignPoints(evt); 43 | this._saveCarouselLengths(evt); 44 | this._startCarouselDataBinding(evt); 45 | }, 46 | 47 | onAfterHide: function (evt) { 48 | this._tearDownCarousel(); 49 | this.removeChildWidget(this._carousel); 50 | this._carousel = null; 51 | }, 52 | 53 | onSelect: function (evt) { 54 | this._goBack(); 55 | }, 56 | 57 | onDataBound: function (evt) { 58 | // In practice you might set widget lengths from data source rather then component args 59 | // and do it during a bind per widget (on append), however if you're doing it in a block 60 | // this is where it needs to happen (post bind, pre align) 61 | if (this._lengths) { 62 | this._carousel.setWidgetLengths(this._lengths); 63 | } 64 | 65 | // tell wrapping strips to generate clones now binding is finished 66 | this._carousel.recalculate(); 67 | 68 | // could set initial/aligned item from data source 69 | this._setCarouselAlignedAndActiveItems(this._initialItem, this._initialItem); 70 | this.show({}); 71 | }, 72 | 73 | setDescription: function (titleText) { 74 | this._description.setText(titleText); 75 | }, 76 | 77 | _addComponentListeners: function () { 78 | var componentEventListenerMap; 79 | componentEventListenerMap = { 80 | 'beforeshow': evtBind(this, 'onBeforeShow'), 81 | 'afterhide': evtBind(this, 'onAfterHide'), 82 | 'select': evtBind(this, 'onSelect') 83 | }; 84 | this._addListenersTo(this, componentEventListenerMap); 85 | }, 86 | 87 | _dontShowYet: function (showEvt) { 88 | showEvt.preventDefault(); 89 | }, 90 | 91 | _createCarousel: function (args) { 92 | this._carousel = new Carousel(args.carouselId, args.orientation); 93 | this._setCarouselNavigatorAndWidgetStrip(args); 94 | 95 | this._attachCarouselHandler(args.animOptions); 96 | }, 97 | 98 | _setCarouselNavigatorAndWidgetStrip: function (args) { 99 | switch (args.type) { 100 | case "WRAPPING": 101 | this._carousel.setWidgetStrip(WrappingStrip); 102 | this._carousel.setNavigator(WrappingNavigator); 103 | break; 104 | case "CULLING": 105 | this._carousel.setWidgetStrip(CullingStrip); 106 | break; 107 | case "HIDING": 108 | this._carousel.setWidgetStrip(HidingStrip); 109 | break; 110 | } 111 | }, 112 | 113 | _attachCarouselHandler: function (animOptions) { 114 | var handler; 115 | handler = new ActivateFirstHandler(); 116 | handler.setAnimationOptions(animOptions); 117 | handler.attach(this._carousel); 118 | }, 119 | 120 | _addCarouselListeners: function () { 121 | this._addListenersTo(this._carousel, this._getCarouselListenerMap()); 122 | }, 123 | 124 | _getCarouselListenerMap: function () { 125 | this._carouselListenerMap = this._carouselListenerMap || { 126 | 'databound': evtBind(this, 'onDataBound') 127 | }; 128 | return this._carouselListenerMap; 129 | }, 130 | 131 | _addListenersTo: function (target, listenerMap) { 132 | this._modifyListenersOn(target, listenerMap, true); 133 | }, 134 | 135 | _modifyListenersOn: function (target, listenerMap, add) { 136 | var eventName, modifyFunction; 137 | modifyFunction = add ? target.addEventListener : target.removeEventListener; 138 | for (eventName in listenerMap) { 139 | if (listenerMap.hasOwnProperty(eventName)) { 140 | modifyFunction.call(target, eventName, listenerMap[eventName]); 141 | } 142 | } 143 | }, 144 | 145 | _setCarouselAlignPoints: function (evt) { 146 | if (evt.args && evt.args.alignment) { 147 | var alignPoint = evt.args.alignment.alignPoint; 148 | var normalisedAlignPoint = evt.args.alignment.normalisedAlignPoint; 149 | var normalisedWidgetAlignPoint = evt.args.alignment.normalisedWidgetAlignPoint; 150 | 151 | if (normalisedAlignPoint) { 152 | this._carousel.setNormalisedAlignPoint(normalisedAlignPoint); 153 | } 154 | 155 | if (normalisedWidgetAlignPoint) { 156 | this._carousel.setNormalisedWidgetAlignPoint(normalisedWidgetAlignPoint); 157 | } 158 | 159 | if (alignPoint) { 160 | this._carousel.setAlignPoint(alignPoint); 161 | } 162 | } 163 | }, 164 | 165 | _saveCarouselLengths: function (evt) { 166 | this._lengths = evt.args.lengths; 167 | }, 168 | 169 | _startCarouselDataBinding: function (evt) { 170 | var dataSource, formatter, binder; 171 | 172 | // disabling auto calc is to prevent wrapping strips from 173 | // creating clones multiple times during a large data bind 174 | this._carousel.autoCalculate(false); 175 | dataSource = evt.args.dataSource; 176 | formatter = evt.args.formatter; 177 | binder = new Binder(formatter, dataSource); 178 | binder.appendAllTo(this._carousel); 179 | }, 180 | 181 | _setCarouselAlignedAndActiveItems: function (alignedIndex, activeIndex) { 182 | this._carousel.alignToIndex(alignedIndex); 183 | this._carousel.setActiveChildIndex(activeIndex); 184 | this._carousel.getChildWidgets()[activeIndex].focus(); 185 | }, 186 | 187 | _goBack: function () { 188 | this.parentWidget.back(); 189 | }, 190 | 191 | /* possibly over cautious but should prevent memory leakage. 192 | * stops running animations, 193 | * removes all items individually (rather then via removeChildWidgets 194 | * as this way clears down widget listeners) then removes any listeners 195 | * added to the carousel. 196 | */ 197 | _tearDownCarousel: function () { 198 | this._carousel.completeAlignment(); 199 | this._removeCarouselItems(); 200 | this._removeCarouselListeners(); 201 | }, 202 | 203 | _removeCarouselItems: function () { 204 | var items; 205 | while (this._carousel.getChildWidgetCount() > 0) { 206 | items = this._carousel.getChildWidgets(); 207 | this._carousel.removeChildWidget(items[0]); 208 | } 209 | }, 210 | 211 | _removeCarouselListeners: function () { 212 | this._removeListenersFrom(this._carousel, this._getCarouselListenerMap()); 213 | }, 214 | 215 | _removeListenersFrom: function (target, listenerMap) { 216 | this._modifyListenersOn(target, listenerMap, false); 217 | } 218 | }); 219 | } 220 | ); 221 | -------------------------------------------------------------------------------- /static/script/appui/components/horizontalprogresscomponent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve Copyright (c) 2014 British Broadcasting Corporation 3 | * (http://www.bbc.co.uk) and TAL Contributors (1) 4 | * 5 | * (1) TAL Contributors are listed in the AUTHORS file and at 6 | * https://github.com/bbc/TAL/AUTHORS - please extend this file, 7 | * not this notice. 8 | * 9 | * @license Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * 21 | * All rights reserved 22 | * Please contact us for an alternative licence 23 | */ 24 | 25 | define( 26 | "sampleapp/appui/components/horizontalprogresscomponent", 27 | [ 28 | "antie/widgets/component", 29 | "antie/widgets/horizontalprogress", 30 | "antie/widgets/label", 31 | "antie/widgets/button" 32 | ], 33 | function (Component, HorizontalProgress, Label, Button) { 34 | 35 | return Component.extend({ 36 | init: function init () { 37 | init.base.call(this, "horizontalprogresscomponent"); 38 | 39 | var button = new Button(); 40 | button.appendChildWidget(new Label("Press SELECT to return to main menu.")); 41 | this.appendChildWidget(button); 42 | 43 | this._progress = new HorizontalProgress("progressBar", true, 0); 44 | this._progress.setText("My Progress Bar!"); 45 | this.appendChildWidget(this._progress); 46 | 47 | var self = this; 48 | 49 | this.addEventListener("aftershow", function (evt) { 50 | self._onAfterShow(evt); 51 | }); 52 | 53 | this.addEventListener("beforehide", function (evt) { 54 | self._onBeforeHide(evt); 55 | }); 56 | 57 | this.addEventListener("select", function(evt) { 58 | self.parentWidget.back(); 59 | }); 60 | }, 61 | 62 | _onAfterShow: function () { 63 | this._progress.setValue(0.0); 64 | var self = this; 65 | 66 | this._intervalID = setInterval( function() { 67 | var value = self._progress.getValue() + 0.1; 68 | 69 | if (value > 1.0) { 70 | value = 1.0; 71 | } 72 | 73 | self._progress.setValue(value); 74 | }, 1000); 75 | }, 76 | 77 | _onBeforeHide: function () { 78 | clearInterval(this._intervalID); 79 | } 80 | }); 81 | 82 | } 83 | ); 84 | -------------------------------------------------------------------------------- /static/script/appui/components/simple.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve Copyright (c) 2013 British Broadcasting Corporation 3 | * (http://www.bbc.co.uk) and TAL Contributors (1) 4 | * 5 | * (1) TAL Contributors are listed in the AUTHORS file and at 6 | * https://github.com/bbc/TAL/AUTHORS - please extend this file, 7 | * not this notice. 8 | * 9 | * @license Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * 21 | * All rights reserved 22 | * Please contact us for an alternative licence 23 | */ 24 | 25 | define( 26 | "sampleapp/appui/components/simple", 27 | [ 28 | "antie/widgets/component", 29 | "antie/widgets/button", 30 | "antie/widgets/label", 31 | "antie/widgets/verticallist", 32 | "antie/widgets/carousel", 33 | "antie/datasource", 34 | "sampleapp/appui/formatters/simpleformatter", 35 | "sampleapp/appui/datasources/simplefeed" 36 | ], 37 | function (Component, Button, Label, VerticalList, Carousel, DataSource, SimpleFormatter, SimpleFeed) { 38 | 39 | // All components extend Component 40 | return Component.extend({ 41 | init: function init () { 42 | var self, helloWorldLabel, welcomeLabel, carouselButtonLabel, verticalListMenu; 43 | 44 | self = this; 45 | 46 | // It is important to call the constructor of the superclass 47 | init.base.call(this, "simplecomponent"); 48 | 49 | // Add the labels to the component 50 | helloWorldLabel = new Label("helloWorldLabel", "Hello World"); 51 | this.appendChildWidget(helloWorldLabel); 52 | 53 | welcomeLabel = new Label("welcomeLabel", "Welcome to your first TAL application!"); 54 | this.appendChildWidget(welcomeLabel); 55 | 56 | var newCarouselButton = this._createCarouselButton(); 57 | 58 | var playerButton = new Button(); 59 | playerButton.addEventListener("select", function(evt){ 60 | self.getCurrentApplication().pushComponent("maincontainer", "sampleapp/appui/components/simplevideocomponent"); 61 | }); 62 | playerButton.appendChildWidget(new Label("Simple Video Player Example")); 63 | 64 | var horizontalProgressButton = new Button(); 65 | horizontalProgressButton.appendChildWidget(new Label("Horizontal Progress Bar Example")); 66 | horizontalProgressButton.addEventListener("select", function(evt) { 67 | self.getCurrentApplication().pushComponent("maincontainer", "sampleapp/appui/components/horizontalprogresscomponent"); 68 | }); 69 | 70 | // Create a vertical list and append the buttons to navigate within the list 71 | verticalListMenu = new VerticalList("mainMenuList"); 72 | verticalListMenu.appendChildWidget(newCarouselButton); 73 | verticalListMenu.appendChildWidget(playerButton); 74 | verticalListMenu.appendChildWidget(horizontalProgressButton); 75 | this.appendChildWidget(verticalListMenu); 76 | 77 | // calls Application.ready() the first time the component is shown 78 | // the callback removes itself once it's fired to avoid multiple calls. 79 | this.addEventListener("aftershow", function appReady(evt) { 80 | self.getCurrentApplication().ready(); 81 | self.removeEventListener('aftershow', appReady); 82 | }); 83 | }, 84 | 85 | _createCarouselButton: function () { 86 | var self = this; 87 | function carouselExampleSelected() { 88 | self.getCurrentApplication().pushComponent( 89 | "maincontainer", 90 | "sampleapp/appui/components/carouselcomponent", 91 | self._getCarouselConfig() 92 | ); 93 | } 94 | 95 | var button = new Button('carouselButton'); 96 | button.appendChildWidget(new Label("Carousel Example")); 97 | button.addEventListener('select', carouselExampleSelected); 98 | return button; 99 | }, 100 | 101 | _getCarouselConfig: function () { 102 | return { 103 | description: "Carousel example, LEFT and RIGHT to navigate, SELECT to go back", 104 | dataSource: new DataSource(null, new SimpleFeed(), 'loadData'), 105 | formatter: new SimpleFormatter(), 106 | orientation: Carousel.orientations.HORIZONTAL, 107 | carouselId: 'verticalCullingCarousel', 108 | animOptions: { 109 | skipAnim: false 110 | }, 111 | alignment: { 112 | normalisedAlignPoint: 0.5, 113 | normalisedWidgetAlignPoint: 0.5 114 | }, 115 | initialItem: 4, 116 | type: "CULLING", 117 | lengths: 264 118 | }; 119 | } 120 | }); 121 | } 122 | ); 123 | -------------------------------------------------------------------------------- /static/script/appui/components/simplevideocomponent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve Copyright (c) 2013 British Broadcasting Corporation 3 | * (http://www.bbc.co.uk) and TAL Contributors (1) 4 | * 5 | * (1) TAL Contributors are listed in the AUTHORS file and at 6 | * https://github.com/bbc/TAL/AUTHORS - please extend this file, 7 | * not this notice. 8 | * 9 | * @license Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * 21 | * All rights reserved 22 | * Please contact us for an alternative licence 23 | */ 24 | 25 | define( 26 | "sampleapp/appui/components/simplevideocomponent", 27 | [ 28 | "antie/widgets/component", 29 | "antie/widgets/button", 30 | "antie/widgets/label", 31 | "antie/widgets/horizontallist", 32 | "antie/videosource", 33 | "antie/devices/mediaplayer/mediaplayer", 34 | "antie/runtimecontext" 35 | ], 36 | function (Component, Button, Label, HorizontalList, VideoSource, MediaPlayer, RuntimeContext) { 37 | 38 | return Component.extend({ 39 | init: function init () { 40 | var self = this; 41 | 42 | // It is important to call the constructor of the superclass 43 | init.base.call(this, "simplevideocomponent"); 44 | 45 | // Get a reference to the current application and device objects 46 | this._application = this.getCurrentApplication(); 47 | this._device = this._application.getDevice(); 48 | 49 | // Create a a label add a class to it, this class can be used as a CSS selector 50 | var description = new Label("Simple Video Component."); 51 | description.addClass("description"); 52 | this.appendChildWidget(description); 53 | 54 | // Create a horizontal list that contains buttons to control the video 55 | var playerControlButtons = new HorizontalList("playerButtons"); 56 | 57 | var play = new Button('play'); 58 | play.appendChildWidget(new Label('PLAY')); 59 | playerControlButtons.appendChildWidget(play); 60 | play.addEventListener('select', function(evt) { 61 | self.getPlayer().resume(); 62 | }); 63 | 64 | var pause = new Button('pause'); 65 | pause.appendChildWidget(new Label('PAUSE')); 66 | playerControlButtons.appendChildWidget(pause); 67 | pause.addEventListener('select', function(evt) { 68 | self.getPlayer().pause(); 69 | }); 70 | 71 | var rewind = new Button('rewind'); 72 | rewind.appendChildWidget(new Label('-5s')); 73 | playerControlButtons.appendChildWidget(rewind); 74 | rewind.addEventListener('select', function(evt) { 75 | var currentTime = self.getPlayer().getCurrentTime(); 76 | self.getPlayer().playFrom(currentTime - 5); 77 | }); 78 | 79 | var fastForward = new Button('fastForward'); 80 | fastForward.appendChildWidget(new Label('+5s')); 81 | playerControlButtons.appendChildWidget(fastForward); 82 | fastForward.addEventListener('select', function(evt) { 83 | var currentTime = self.getPlayer().getCurrentTime(); 84 | self.getPlayer().playFrom(currentTime + 5); 85 | }); 86 | 87 | var back = new Button('back'); 88 | back.appendChildWidget(new Label('BACK')); 89 | playerControlButtons.appendChildWidget(back); 90 | back.addEventListener('select', function(evt) { 91 | // Make sure we destroy the player before exiting 92 | self.destroyPlayer(); 93 | self.parentWidget.back(); 94 | }); 95 | 96 | // Append the player control buttons to the component 97 | this.appendChildWidget(playerControlButtons); 98 | 99 | // Add a 'beforerender' event listener to the component that takes care of video instantiation 100 | this.addEventListener("beforerender", function (evt) { 101 | self._onBeforeRender(evt); 102 | }); 103 | }, 104 | 105 | _onBeforeRender: function (ev) { 106 | // Create the device's video object, set the media sources and start loading the media 107 | var videoContainer = RuntimeContext.getCurrentApplication().getRootWidget().outputElement; 108 | var player = this.getPlayer() 109 | player.initialiseMedia('video', "static/mp4/spinning-logo.mp4", "video/mp4", videoContainer); 110 | player.beginPlayback(); 111 | }, 112 | 113 | getPlayer: function() { 114 | return RuntimeContext.getDevice().getMediaPlayer(); 115 | }, 116 | 117 | destroyPlayer: function() { 118 | this.getPlayer().stop(); 119 | this.getPlayer().reset(); 120 | }, 121 | 122 | showBackground: function() { 123 | if (this._device.getPlayerEmbedMode() === Media.EMBED_MODE_BACKGROUND) { 124 | this._device.removeClassFromElement(document.body, 'background-none'); 125 | this._application.getRootWidget().removeClass('background-none'); 126 | } 127 | } 128 | }); 129 | } 130 | ); 131 | -------------------------------------------------------------------------------- /static/script/appui/datasources/simplefeed.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve Copyright (c) 2013 British Broadcasting Corporation 3 | * (http://www.bbc.co.uk) and TAL Contributors (1) 4 | * 5 | * (1) TAL Contributors are listed in the AUTHORS file and at 6 | * https://github.com/bbc/TAL/AUTHORS - please extend this file, 7 | * not this notice. 8 | * 9 | * @license Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * 21 | * All rights reserved 22 | * Please contact us for an alternative licence 23 | */ 24 | 25 | define( 26 | "sampleapp/appui/datasources/simplefeed", 27 | [ 28 | "antie/class" 29 | ], 30 | function(Class) { 31 | return Class.extend({ 32 | // You will probably want to do something more useful then returning static data 33 | loadData : function(callbacks) { 34 | callbacks.onSuccess( 35 | [ 36 | { 37 | "id":"1", 38 | "title":"Apple", 39 | "img" : "static/img/fruit/apple.png" 40 | }, 41 | { 42 | "id":"2", 43 | "title":"Banana", 44 | "img" : "static/img/fruit/banana.png" 45 | }, 46 | { 47 | "id":"3", 48 | "title":"Grapes", 49 | "img" : "static/img/fruit/grapes.png" 50 | }, 51 | { 52 | "id":"4", 53 | "title":"Orange", 54 | "img" : "static/img/fruit/orange.png" 55 | }, 56 | { 57 | "id":"5", 58 | "title":"Peach", 59 | "img" : "static/img/fruit/peach.png" 60 | }, 61 | { 62 | "id":"6", 63 | "title":"Pear", 64 | "img" : "static/img/fruit/pear.png" 65 | } 66 | ] 67 | ); 68 | } 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /static/script/appui/formatters/simpleformatter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve Copyright (c) 2013 British Broadcasting Corporation 3 | * (http://www.bbc.co.uk) and TAL Contributors (1) 4 | * 5 | * (1) TAL Contributors are listed in the AUTHORS file and at 6 | * https://github.com/bbc/TAL/AUTHORS - please extend this file, 7 | * not this notice. 8 | * 9 | * @license Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * 21 | * All rights reserved 22 | * Please contact us for an alternative licence 23 | */ 24 | 25 | define( 26 | "sampleapp/appui/formatters/simpleformatter", 27 | [ 28 | "antie/formatter", 29 | "antie/widgets/label", 30 | "antie/widgets/button", 31 | "antie/widgets/image" 32 | ], 33 | function(Formatter, Label, Button, Image) { 34 | return Formatter.extend({ 35 | format : function (iterator) { 36 | var button, item; 37 | item = iterator.next(); 38 | button = new Button("fruit" + item.id); 39 | button.appendChildWidget(new Image("img-item.id", item.img, { width : 200, height: 200})); 40 | button.appendChildWidget(new Label(item.title)); 41 | return button; 42 | } 43 | }); 44 | } 45 | ); 46 | -------------------------------------------------------------------------------- /static/script/appui/layouts/1080p.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve Copyright (c) 2013 British Broadcasting Corporation 3 | * (http://www.bbc.co.uk) and TAL Contributors (1) 4 | * 5 | * (1) TAL Contributors are listed in the AUTHORS file and at 6 | * https://github.com/bbc/TAL/AUTHORS - please extend this file, 7 | * not this notice. 8 | * 9 | * @license Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * 21 | * All rights reserved 22 | * Please contact us for an alternative licence 23 | */ 24 | 25 | define( 26 | 'sampleapp/appui/layouts/1080p', 27 | { 28 | classes: [ 29 | "layout1080p" 30 | ], 31 | css: [ 32 | "layouts/1080p.css" 33 | ], 34 | requiredScreenSize: { 35 | width: 1920, 36 | height: 1080 37 | } 38 | } 39 | ); 40 | -------------------------------------------------------------------------------- /static/script/appui/layouts/540p.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve Copyright (c) 2013 British Broadcasting Corporation 3 | * (http://www.bbc.co.uk) and TAL Contributors (1) 4 | * 5 | * (1) TAL Contributors are listed in the AUTHORS file and at 6 | * https://github.com/bbc/TAL/AUTHORS - please extend this file, 7 | * not this notice. 8 | * 9 | * @license Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * 21 | * All rights reserved 22 | * Please contact us for an alternative licence 23 | */ 24 | 25 | define( 26 | 'sampleapp/appui/layouts/540p', 27 | { 28 | classes: [ 29 | "layout540p" 30 | ], 31 | css: [ 32 | "layouts/540p.css" 33 | ], 34 | requiredScreenSize: { 35 | width: 960, 36 | height: 540 37 | } 38 | } 39 | ); 40 | -------------------------------------------------------------------------------- /static/script/appui/layouts/720p.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve Copyright (c) 2013 British Broadcasting Corporation 3 | * (http://www.bbc.co.uk) and TAL Contributors (1) 4 | * 5 | * (1) TAL Contributors are listed in the AUTHORS file and at 6 | * https://github.com/bbc/TAL/AUTHORS - please extend this file, 7 | * not this notice. 8 | * 9 | * @license Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * 21 | * All rights reserved 22 | * Please contact us for an alternative licence 23 | */ 24 | 25 | define( 26 | 'sampleapp/appui/layouts/720p', 27 | { 28 | classes: [ 29 | "layout720p" 30 | ], 31 | css: [ 32 | "layouts/720p.css" 33 | ], 34 | requiredScreenSize: { 35 | width: 1280, 36 | height: 720 37 | } 38 | } 39 | ); 40 | -------------------------------------------------------------------------------- /static/script/appui/sampleapp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve Copyright (c) 2013 British Broadcasting Corporation 3 | * (http://www.bbc.co.uk) and TAL Contributors (1) 4 | * 5 | * (1) TAL Contributors are listed in the AUTHORS file and at 6 | * https://github.com/bbc/TAL/AUTHORS - please extend this file, 7 | * not this notice. 8 | * 9 | * @license Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * 21 | * All rights reserved 22 | * Please contact us for an alternative licence 23 | */ 24 | 25 | define( 26 | 'sampleapp/appui/sampleapp', 27 | [ 28 | 'antie/application', 29 | 'antie/widgets/container' 30 | ], 31 | function(Application, Container) { 32 | 33 | return Application.extend({ 34 | init: function init (appDiv, styleDir, imgDir, callback) { 35 | init.base.call(this, appDiv, styleDir, imgDir, callback); 36 | 37 | var self = this; 38 | 39 | // Sets the root widget of the application to be an empty container 40 | this._setRootContainer = function() { 41 | var container = new Container(); 42 | container.outputElement = appDiv; 43 | self.setRootWidget(container); 44 | }; 45 | }, 46 | 47 | run: function() { 48 | // Called from run() as we need the framework to be ready beforehand. 49 | this._setRootContainer(); 50 | 51 | // Create maincontainer and add simple component to it 52 | this.addComponentContainer("maincontainer", "sampleapp/appui/components/simple"); 53 | } 54 | }); 55 | } 56 | ); 57 | -------------------------------------------------------------------------------- /static/style/base.css: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve Copyright (c) 2013 British Broadcasting Corporation 3 | * (http://www.bbc.co.uk) and TAL Contributors (1) 4 | * 5 | * (1) TAL Contributors are listed in the AUTHORS file and at 6 | * https://github.com/bbc/TAL/AUTHORS - please extend this file, 7 | * not this notice. 8 | * 9 | * @license Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * 21 | * All rights reserved 22 | * Please contact us for an alternative licence 23 | */ 24 | 25 | html { 26 | height: 100%; 27 | } 28 | 29 | body { 30 | overflow: hidden; 31 | height: 100%; 32 | margin: 0; 33 | padding: 0; 34 | font-family: "Helvetica", sans-serif; 35 | font-weight: lighter; 36 | color: #d4d4d4; 37 | background-color: #000000; 38 | } 39 | 40 | object { 41 | position: absolute; 42 | } 43 | 44 | /* Loading screen */ 45 | #static-loading-screen { 46 | position: absolute; 47 | margin-top: 100px; 48 | z-index: 100; 49 | width: 100%; 50 | } 51 | 52 | #static-loading-screen p { 53 | text-align: center; 54 | font-size: 28px; 55 | font-weight: bold; 56 | margin: 20px 0; 57 | padding: 0 50px; 58 | } 59 | 60 | /* List widgets */ 61 | .horizontallist, .verticallist { 62 | position: relative; 63 | } 64 | 65 | .horizontallist .listitem { 66 | display: inline-block; 67 | } 68 | 69 | /* nested lists - use #IDs instead for more complex layouts */ 70 | .verticallist .horizontallist .listitem { 71 | display: inline-block; 72 | } 73 | 74 | .verticallist .listitem { 75 | display: block; 76 | position: relative; 77 | } 78 | 79 | /* nested lists - use #IDs instead for more complex layouts */ 80 | .horizontallist .verticallist .listitem { 81 | display: block; 82 | } 83 | 84 | /* Horizontal carousel widgets */ 85 | /* the mask is the top level of the carousel and defines where it is displayed and how much is visible */ 86 | .horizontallistmask { 87 | overflow: hidden; 88 | width: 100%; 89 | } 90 | 91 | /* ensure nested carousels have correct formatting, you may need to target IDs in complex layouts */ 92 | .horizontallistmask .horizontallist .listitem { 93 | display: inline-block; 94 | } 95 | 96 | .horizontalcarousel { 97 | width: 99999px; /* needs to be big enough so carousel plus clones do not flow onto more then one line */ 98 | } 99 | 100 | /* DEVICE SPECIFIC DEFAULTS EXAMPLE ------------------ */ 101 | 102 | /* if you target some consoles you may need to add additional styles like this */ 103 | .someConsoles .horizontallist .listitem { 104 | display: inline-block; 105 | float: left; 106 | } 107 | 108 | /* If you target some older tv models, you will need to specify 109 | initial element background in the base stylesheet, not in dynamically loaded styles. */ 110 | 111 | .sometv.layout540p #app { 112 | width: 960px; 113 | height: 540px; 114 | /*background-image: url(some/image/url_540.png); */ 115 | } 116 | 117 | .sometv.layout720p #app { 118 | width: 1280px; 119 | height: 720px; 120 | /*background-image: url(some/image/url_720.png); */ 121 | } 122 | 123 | .sometv.layout1080p #app { 124 | width: 1920px; 125 | height: 1080px; 126 | /*background-image: url(some/image/url_1080.png); */ 127 | } 128 | 129 | /* SAMPLEAPP BASE STYLES */ 130 | 131 | /* Core */ 132 | 133 | /* Maple needs initial element background in base stylesheet... not in dynamically loaded styles! */ 134 | .samsung.layout540p #app { 135 | width: 960px; 136 | height: 540px; 137 | background-image: url(../img/bbc_background_540.png); 138 | background-repeat: no-repeat; 139 | background-color: red; 140 | } 141 | 142 | .samsung.layout720p #app { 143 | width: 1280px; 144 | height: 720px; 145 | background-image: url(../img/bbc_background_720.png); 146 | background-repeat: no-repeat; 147 | } 148 | 149 | .samsung.layout1080p #app { 150 | width: 1920px; 151 | height: 1080px; 152 | background-image: url(../img/bbc_background_1080.png); 153 | background-repeat: no-repeat; 154 | } 155 | 156 | 157 | /* Sample app specific styles */ 158 | #title { 159 | font-size: 150%; 160 | line-height: 120%; 161 | display: block; 162 | text-align: center; 163 | margin: 2% auto 0 auto; 164 | } 165 | 166 | .button { 167 | background-color: #DCDCDC; 168 | display: block; 169 | text-align: center; 170 | max-width: 600px; 171 | padding: 8px; 172 | margin: 8px auto 0 auto; 173 | color: #000000; 174 | } 175 | 176 | .buttonFocussed { 177 | background-color: #FFD700; 178 | color: #000000; 179 | } 180 | 181 | .buttonFocussed.menuendpoint { 182 | background-color: #FFD700; 183 | } 184 | 185 | .background-none { 186 | background-image: none !important; 187 | background-color: transparent !important; 188 | } 189 | 190 | .description { 191 | text-align: center; 192 | display: block; 193 | position: absolute; 194 | width: 100%; 195 | background-color: rgba(0, 0, 0, 0.5); 196 | z-index: 1; 197 | padding: 8px 0px; 198 | } 199 | 200 | #testPlayer { 201 | z-index: 0; 202 | position: absolute; 203 | top: 0px; 204 | left: 0px; 205 | width: 1280px; 206 | height: 720px; 207 | } 208 | 209 | #playerButtons { 210 | z-index: 1; 211 | position: absolute; 212 | background-color: rgba(0, 0, 0, 0.5); 213 | display: block; 214 | text-align: center; 215 | padding: 8px; 216 | color: #000000; 217 | } 218 | 219 | #playerButtons .button { 220 | width: 75px; 221 | padding: 10px; 222 | text-align: center; 223 | margin: 5px; 224 | } 225 | 226 | /* Display & Visibility Helpers */ 227 | .display-none { 228 | display: none !important; 229 | } 230 | 231 | .visibility-hidden { 232 | visibility: hidden !important; 233 | } 234 | 235 | .carouselmask { 236 | overflow: hidden; 237 | } 238 | 239 | .carouselwidgetstrip { 240 | position: relative; 241 | white-space: nowrap; 242 | } 243 | 244 | .carouselwidgetstrip.vertical > .carouselItem { 245 | display: block; 246 | } 247 | 248 | .carouselwidgetstrip.horizontal > .carouselItem { 249 | display: inline-block; 250 | } 251 | 252 | #carouselComponent { 253 | position: relative; 254 | } 255 | 256 | #carouselComponent > .carouselmask { 257 | margin-left: auto; 258 | margin-right: auto; 259 | } 260 | 261 | #carouselComponent > .description { 262 | position: static; 263 | } 264 | 265 | .carouselwidgetstrip > .button { 266 | margin: 0; 267 | width: 200px; 268 | padding: 32px; 269 | } 270 | 271 | .carouselwidgetstrip.vertical > .button { 272 | height: 200px; 273 | } 274 | 275 | #progressBar { 276 | margin-top: 10%; 277 | width: 50%; 278 | margin-left: 25%; 279 | min-height: 10px; 280 | background: #070; 281 | } 282 | #progressBar_left { 283 | min-height: 10px; 284 | background: #700; 285 | } 286 | #progressBar_inner { 287 | width: 10px; 288 | min-height: 10px; 289 | background: #777; 290 | position: relative; 291 | } 292 | -------------------------------------------------------------------------------- /static/style/layouts/1080p.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/talexample/34d0b343caa2588ee8b1c7e9408b87be365f1a7c/static/style/layouts/1080p.css -------------------------------------------------------------------------------- /static/style/layouts/540p.css: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve Copyright (c) 2013 British Broadcasting Corporation 3 | * (http://www.bbc.co.uk) and TAL Contributors (1) 4 | * 5 | * (1) TAL Contributors are listed in the AUTHORS file and at 6 | * https://github.com/bbc/TAL/AUTHORS - please extend this file, 7 | * not this notice. 8 | * 9 | * @license Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * 21 | * All rights reserved 22 | * Please contact us for an alternative licence 23 | */ 24 | 25 | /* RESOLUTION SPECIFIC STYLES - 960px X 540px */ 26 | /* Application in Center-Middle of Screen (achieved by positioning 50% down from top AND shifting back up to origin by half height) */ 27 | #app { 28 | position: relative; 29 | overflow: hidden; 30 | width: 960px; 31 | height: 540px; 32 | top: 50%; 33 | margin: -270px auto 0 auto; 34 | background-image: url(../../img/bbc_background_540.png); 35 | background-repeat: no-repeat; 36 | background-color: red; 37 | } 38 | 39 | #helloWorldLabel, #welcomeLabel { 40 | display: block; 41 | text-align: center; 42 | } 43 | 44 | #helloWorldLabel { 45 | font-size: 45px; 46 | padding-top: 175px; 47 | font-weight: bold; 48 | } 49 | 50 | #welcomeLabel { 51 | font-size: 25px; 52 | } 53 | 54 | #simplecarousel_mask { 55 | top: 120px; 56 | } 57 | 58 | .description { 59 | top: 50px; 60 | font-size: 20px; 61 | } 62 | 63 | #playerButtons { 64 | bottom: 30px; 65 | width: 600px; 66 | padding: 8px; 67 | left: 180px; 68 | } 69 | 70 | #carouselComponent > .carouselmask.horizontal { 71 | width: 720px; 72 | } 73 | 74 | #carouselComponent > .carouselmask.vertical { 75 | height: 450px; 76 | width: 264px 77 | } 78 | 79 | #carouselComponent > .description { 80 | margin-bottom: 32px; 81 | } -------------------------------------------------------------------------------- /static/style/layouts/720p.css: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve Copyright (c) 2013 British Broadcasting Corporation 3 | * (http://www.bbc.co.uk) and TAL Contributors (1) 4 | * 5 | * (1) TAL Contributors are listed in the AUTHORS file and at 6 | * https://github.com/bbc/TAL/AUTHORS - please extend this file, 7 | * not this notice. 8 | * 9 | * @license Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * 21 | * All rights reserved 22 | * Please contact us for an alternative licence 23 | */ 24 | 25 | /* RESOLUTION SPECIFIC STYLES - 1280px X 720px */ 26 | /* Application in Center-Middle of Screen (achieved by positioning 50% down from top AND shifting back up to origin by half height) */ 27 | #app { 28 | position: relative; 29 | overflow: hidden; 30 | width: 1280px; 31 | height: 720px; 32 | top: 50%; 33 | margin: -360px auto 0 auto; 34 | background-image: url(../../img/bbc_background_720.png); 35 | } 36 | 37 | #helloWorldLabel, #welcomeLabel { 38 | display: block; 39 | text-align: center; 40 | } 41 | 42 | #helloWorldLabel { 43 | font-size: 60px; 44 | padding-top: 228px; 45 | font-weight: bold; 46 | } 47 | 48 | #welcomeLabel { 49 | font-size: 26px; 50 | } 51 | 52 | #simplecarousel_mask { 53 | top: 156px; 54 | } 55 | 56 | 57 | .description { 58 | top: 65px; 59 | font-size: 26px; 60 | } 61 | 62 | #playerButtons { 63 | bottom: 39px; 64 | width: 780px; 65 | padding: 10px; 66 | left: 235px; 67 | } 68 | 69 | #carouselComponent > .carouselmask.horizontal { 70 | width: 960px; 71 | } 72 | 73 | #carouselComponent > .carouselmask.vertical { 74 | height: 600px; 75 | width: 264px 76 | } 77 | 78 | #carouselComponent > .description { 79 | margin-bottom: 64px; 80 | } -------------------------------------------------------------------------------- /views/error.mustache: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{> imports}} 5 | 6 | 7 | 8 |
9 |

Device configuration not supported:

10 |

{{ exception }}

11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /views/imports.mustache: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /views/index.mustache: -------------------------------------------------------------------------------- 1 | {{{ root_html_tag }}} 2 | 3 | 4 | 5 | {{{ headers }}} 6 | 7 | 18 | 19 | {{> imports}} 20 | 21 | 28 | 29 | 30 | 31 | 32 | {{{ extra_body }}} 33 | 34 |
35 |

Application is loading...

36 |
37 | 38 | 39 | 40 | 58 | 59 | 60 | 61 | --------------------------------------------------------------------------------