transcoding: redesigned the 10-foot javascript client.
navigation is done using a keyboard (no mouse scrolling or touch events are supported). double clicking a channel (or pressing the enter key while being selected) will tune to a channel. the channel list can be hidden by pressing esc or backspace, and brought back by pressing enter. page-up and page-down are also supported.
This commit is contained in:
parent
9259102090
commit
824b0c0ca6
3 changed files with 430 additions and 248 deletions
|
@ -1,43 +1,113 @@
|
|||
body {
|
||||
font-size : 150%;
|
||||
color : #b2afa8;
|
||||
background: black;
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
#tv_videoPlayer {
|
||||
z-index: 0;
|
||||
width:100%;
|
||||
margin-right:auto;
|
||||
margin-left:auto;
|
||||
display:block;
|
||||
.x-hide-display {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#tv_channelList {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#tv_statusBar {
|
||||
.x-panel {
|
||||
z-index : 1;
|
||||
position: fixed;
|
||||
bottom: 5%;
|
||||
|
||||
padding: 5px;
|
||||
|
||||
border-radius: 10px;
|
||||
background: rgba(128, 128, 128, 0.7);
|
||||
width: 80%;
|
||||
left: 10%;
|
||||
z-index: 1;
|
||||
border : double 5px #000000;
|
||||
|
||||
box-shadow: 10px 10px 15px #000000;
|
||||
|
||||
background:
|
||||
radial-gradient(black 15%, transparent 16%) 0 0,
|
||||
radial-gradient(black 15%, transparent 16%) 8px 8px,
|
||||
radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 0 1px,
|
||||
radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 8px 9px;
|
||||
|
||||
background-color: rgba(28,28,28,0.7);
|
||||
background-size : 16px 16px;
|
||||
}
|
||||
|
||||
#tv_statusBar table {
|
||||
padding: 5px;
|
||||
.x-panel-header {
|
||||
text-align: center;
|
||||
border-bottom: solid 2px black;
|
||||
|
||||
margin-left : 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.x-panel-header-text {
|
||||
font-size : 150%;
|
||||
font-weight : bold;
|
||||
}
|
||||
|
||||
.tv-list {
|
||||
overflow: hidden;
|
||||
outline : 0;
|
||||
}
|
||||
|
||||
.tv-list-item {
|
||||
padding : 5px;
|
||||
height : 64px;
|
||||
font-size : 120%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#sb_channelLogo {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
float: left;
|
||||
margin: 5px;
|
||||
cursor: pointer;
|
||||
.tv-list-item img {
|
||||
height : 100%;
|
||||
width : 64px;
|
||||
display: inline;
|
||||
|
||||
vertical-align: middle;
|
||||
|
||||
padding-left : 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
#sb_channelName, #sb_nowTitle, #sb_nextTitle {
|
||||
width: 100%;
|
||||
}
|
||||
.tv-list-item-selected {
|
||||
color : white;
|
||||
border : solid 1px #4180eb;
|
||||
border-radius: 10px;
|
||||
background : linear-gradient(#4180eb 0%, #366dab 100%);
|
||||
}
|
||||
|
||||
.tv-video-player {
|
||||
z-index : 0;
|
||||
position : fixed;
|
||||
margin-right: auto;
|
||||
margin-left : auto;
|
||||
|
||||
width : 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tv-channel-list {
|
||||
z-index : 1;
|
||||
position: fixed;
|
||||
top : 8%;
|
||||
left : 5%;
|
||||
height : 80%;
|
||||
}
|
||||
|
||||
.tv-video-idle {
|
||||
background-color : #000;
|
||||
background-image : url(../docresources/tvheadendlogo.png);
|
||||
background-repeat : no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-position : center;
|
||||
}
|
||||
|
||||
.tv-video-loading {
|
||||
background-image : url(./img/spinner_black_bg.gif);
|
||||
background-repeat : no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-position : center;
|
||||
}
|
||||
|
||||
.tv-video-error {
|
||||
background-image : url(./img/error.png);
|
||||
background-repeat : no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-position : center;
|
||||
}
|
||||
|
|
|
@ -2,33 +2,14 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Tvheadend</title>
|
||||
<link rel="stylesheet" type="text/css" href="tv.css">
|
||||
<script type="text/javascript" src="extjs/adapter/ext/ext-base.js"></script>
|
||||
<script type="text/javascript" src="extjs/ext-all.js"></script>
|
||||
<script type="text/javascript" src="tv.js"></script>
|
||||
<script type="text/javascript">
|
||||
Ext.onReady(tv.app.init, tv.app);
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="tv.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="tv_statusBar">
|
||||
<img id="sb_channelLogo" src="htslogo.png">
|
||||
<table>
|
||||
<tr>
|
||||
<td id="sb_channelName"></td>
|
||||
<td id="sb_currentTime"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="sb_nowTitle"></td>
|
||||
<td id="sb_nowDuration"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="sb_nextTitle"></td>
|
||||
<td id="sb_nextDuration"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<video id="tv_videoPlayer"></video>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
|
||||
Ext.namespace('tv');
|
||||
Ext.namespace('tv.ui');
|
||||
|
||||
if (VK_LEFT === undefined)
|
||||
var VK_LEFT = 0x25;
|
||||
|
||||
|
@ -26,86 +29,23 @@ if (VK_STOP === undefined)
|
|||
if (VK_BACK === undefined)
|
||||
var VK_BACK = 0xa6;
|
||||
|
||||
Ext.namespace('tv');
|
||||
if (VK_ESCAPE === undefined)
|
||||
var VK_ESCAPE = 0x1b;
|
||||
|
||||
tv.baseUrl = '../';
|
||||
if (VK_BACKSPACE === undefined)
|
||||
var VK_BACKSPACE = 0x08;
|
||||
|
||||
tv.channelTags = new Ext.data.JsonStore({
|
||||
autoLoad : true,
|
||||
root : 'entries',
|
||||
fields : [ 'identifier', 'name' ],
|
||||
id : 'identifier',
|
||||
sortInfo : {
|
||||
field : 'name',
|
||||
direction : "ASC"
|
||||
},
|
||||
url : tv.baseUrl + 'channeltags',
|
||||
baseParams : {
|
||||
op : 'listTags'
|
||||
}
|
||||
});
|
||||
if (VK_SPACE === undefined)
|
||||
var VK_SPACE = 0x20;
|
||||
|
||||
tv.channels = new Ext.data.JsonStore({
|
||||
autoLoad : true,
|
||||
root : 'entries',
|
||||
fields : ['ch_icon', 'number', 'name', 'chid', 'tags'],
|
||||
id : 'chid',
|
||||
sortInfo : {
|
||||
field : 'number',
|
||||
direction : "ASC"
|
||||
},
|
||||
url : tv.baseUrl + "channels",
|
||||
baseParams : {
|
||||
op : 'list'
|
||||
}
|
||||
});
|
||||
if (VK_PAGE_UP === undefined)
|
||||
var VK_PAGE_UP = 0x21;
|
||||
|
||||
tv.epg = new Ext.data.JsonStore({
|
||||
url : tv.baseUrl + "epg",
|
||||
bufferSize : 300,
|
||||
root : 'entries',
|
||||
fields : [ 'id' ,
|
||||
'channel',
|
||||
'channelid',
|
||||
'title',
|
||||
'subtitle',
|
||||
'episode',
|
||||
'description',
|
||||
'chicon',
|
||||
{
|
||||
name : 'start',
|
||||
type : 'date',
|
||||
dateFormat : 'U' // unix time
|
||||
},
|
||||
{
|
||||
name : 'end',
|
||||
type : 'date',
|
||||
dateFormat : 'U' // unix time
|
||||
},
|
||||
'duration',
|
||||
'contenttype',
|
||||
'schedstate',
|
||||
'serieslink',
|
||||
],
|
||||
baseParams : {
|
||||
limit : 2
|
||||
}
|
||||
});
|
||||
if (VK_PAGE_DOWN === undefined)
|
||||
var VK_PAGE_DOWN = 0x22;
|
||||
|
||||
|
||||
tv.ui = function() {
|
||||
//private space
|
||||
|
||||
// public space
|
||||
return {
|
||||
};
|
||||
|
||||
}(); // end of ui
|
||||
|
||||
|
||||
|
||||
tv.playback = function() {
|
||||
//private space
|
||||
tv.ui.VideoPlayer = Ext.extend(Ext.Panel, (function() {
|
||||
|
||||
var profiles = {
|
||||
pass: {
|
||||
|
@ -158,34 +98,14 @@ tv.playback = function() {
|
|||
}
|
||||
};
|
||||
|
||||
// public space
|
||||
return {
|
||||
getProfile: function() {
|
||||
var vid = document.createElement('video');
|
||||
constructor: function(config) {
|
||||
this.params = {};
|
||||
tv.ui.VideoPlayer.superclass.constructor.call(this, config);
|
||||
|
||||
// chrome can handle h264+aac within mkv, given that h264 codecs are available
|
||||
if(Ext.isChrome &&
|
||||
vid.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"') == 'probably')
|
||||
return profiles['mkv'];
|
||||
|
||||
for (var key in profiles)
|
||||
if(vid.canPlayType(profiles[key].mimetype) == 'probably')
|
||||
return profiles[key];
|
||||
|
||||
for (var key in profiles)
|
||||
if(vid.canPlayType(profiles[key].mimetype) == 'maybe')
|
||||
return profiles[key];
|
||||
|
||||
return {};
|
||||
},
|
||||
|
||||
getUrl: function(chid, config) {
|
||||
var config = config || {}
|
||||
var params = {}
|
||||
|
||||
Ext.apply(params, this.getProfile(), {
|
||||
Ext.applyIf(this.params, {
|
||||
transcode : 0,
|
||||
resolution: 384,
|
||||
resolution: 288,
|
||||
channels : 0, // same as source
|
||||
bandwidth : 0, // same as source
|
||||
language : '', // same as source
|
||||
|
@ -195,15 +115,60 @@ tv.playback = function() {
|
|||
muxer : '', // default dvr config
|
||||
playlist : false // don't use m3u8 playlist
|
||||
});
|
||||
Ext.apply(params, config);
|
||||
|
||||
var url = tv.baseUrl;
|
||||
},
|
||||
|
||||
initComponent: function() {
|
||||
Ext.apply(this, {
|
||||
baseCls : 'tv-video-player',
|
||||
bodyStyle : 'background-color:#000;color:#fff',
|
||||
html : '',
|
||||
bufferLength: 3000, //ms
|
||||
|
||||
listeners: {
|
||||
beforedestroy: {
|
||||
fn: function(dv, items) {
|
||||
this.video = null;
|
||||
}
|
||||
},
|
||||
bodyresize: {
|
||||
fn: function(panel, width, height) {
|
||||
this.video.setSize(width, height);
|
||||
}
|
||||
},
|
||||
render: {
|
||||
fn: function() {
|
||||
this.video = this.body.createChild({
|
||||
tag : 'video',
|
||||
width : '100%',
|
||||
height : '100%',
|
||||
html : "Your browser doesn't support html5 video"
|
||||
});
|
||||
this.source = this.video.createChild({tag: 'source'});
|
||||
this.source.dom.addEventListener('error', this.error.bind(this));
|
||||
|
||||
this.stop();
|
||||
|
||||
var self = this;
|
||||
this.video.dom.addEventListener('loadeddata', function() {
|
||||
setTimeout(function() {
|
||||
self.play();
|
||||
}, self.bufferLength); //buffer 3000ms
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
tv.ui.VideoPlayer.superclass.initComponent.apply(this, arguments);
|
||||
},
|
||||
|
||||
_getUrl: function(chid, params) {
|
||||
var url = '../';
|
||||
|
||||
if(params.playlist)
|
||||
url += 'playlist/channelid/'
|
||||
else
|
||||
url += 'stream/channelid/'
|
||||
|
||||
|
||||
url += chid;
|
||||
url += "?transcode=" + new Number(params.transcode);
|
||||
url += "&mux=" + params.muxer;
|
||||
|
@ -213,126 +178,292 @@ tv.playback = function() {
|
|||
url += "&resolution=" + params.resolution;
|
||||
url += "&bandwidth=" + params.bandwidth;
|
||||
url += "&language=" + params.language;
|
||||
|
||||
|
||||
return url;
|
||||
},
|
||||
|
||||
_getProfile: function() {
|
||||
var el = this.video.dom;
|
||||
|
||||
// chrome can handle h264+aac within mkv, given that h264 codecs are available
|
||||
if(Ext.isChrome &&
|
||||
el.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"') == 'probably')
|
||||
return profiles['mkv'];
|
||||
|
||||
for (var key in profiles)
|
||||
if(el.canPlayType(profiles[key].mimetype) == 'probably')
|
||||
return profiles[key];
|
||||
|
||||
for (var key in profiles)
|
||||
if(el.canPlayType(profiles[key].mimetype) == 'maybe')
|
||||
return profiles[key];
|
||||
|
||||
return {};
|
||||
},
|
||||
|
||||
error: function() {
|
||||
var url = this.source.dom.src;
|
||||
if(url && url != document.location.href) {
|
||||
this.body.removeClass('tv-video-loading');
|
||||
this.body.removeClass('tv-video-idle');
|
||||
this.body.addClass('tv-video-error');
|
||||
this.video.hide();
|
||||
}
|
||||
},
|
||||
|
||||
stop: function() {
|
||||
this.body.removeClass('tv-video-loading');
|
||||
this.body.removeClass('tv-video-error');
|
||||
this.body.addClass('tv-video-idle');
|
||||
this.source.dom.src = '';
|
||||
this.video.dom.load();
|
||||
},
|
||||
|
||||
play: function() {
|
||||
this.body.removeClass('tv-video-loading');
|
||||
this.body.removeClass('tv-video-idle');
|
||||
this.body.removeClass('tv-video-error');
|
||||
|
||||
this.video.show();
|
||||
this.video.dom.play();
|
||||
},
|
||||
|
||||
zapTo: function(chid, config) {
|
||||
var config = config || {}
|
||||
var params = {}
|
||||
|
||||
Ext.apply(params, this._getProfile(), this.params);
|
||||
Ext.apply(params, config);
|
||||
|
||||
this.video.hide();
|
||||
this.stop();
|
||||
|
||||
this.body.removeClass('tv-video-idle');
|
||||
this.body.removeClass('tv-video-error');
|
||||
this.body.addClass('tv-video-loading');
|
||||
|
||||
this.source.dom.src = this._getUrl(chid, params);
|
||||
this.video.dom.load();
|
||||
}
|
||||
};
|
||||
}()));
|
||||
|
||||
}(); // end of player
|
||||
|
||||
tv.app = function() {
|
||||
//private space
|
||||
tv.ui.ChannelList = Ext.extend(Ext.DataView, {
|
||||
|
||||
var updateClock = new Ext.util.DelayedTask(function() {
|
||||
var clock = Ext.get('sb_currentTime');
|
||||
clock.update(new Date().toLocaleTimeString());
|
||||
updateClock.delay(1000);
|
||||
});
|
||||
initComponent: function() {
|
||||
Ext.apply(this, {
|
||||
cls: 'tv-list',
|
||||
overClass: 'tv-list-item-over',
|
||||
selectedClass: 'tv-list-item-selected',
|
||||
itemSelector:'div.tv-list-item',
|
||||
singleSelect: true,
|
||||
tpl: new Ext.XTemplate(
|
||||
'<tpl for=".">',
|
||||
'<div class="tv-list-item" id="chid_{chid}">',
|
||||
'<img src="{ch_icon}" title="{name}">{name}',
|
||||
'</div>',
|
||||
'</tpl>'),
|
||||
|
||||
var currentChannel = -1;
|
||||
var initKeyboard = function() {
|
||||
listeners: {
|
||||
selectionchange: {
|
||||
fn: function(dv, items) {
|
||||
if(items.length == 0)
|
||||
return;
|
||||
|
||||
var channelLogoEl = document.getElementById('sb_channelLogo');
|
||||
channelLogoEl.onclick = function() {
|
||||
currentChannel += 1;
|
||||
ch = tv.channels.getAt(currentChannel);
|
||||
onChannelZap(ch.data);
|
||||
}
|
||||
var node = this.getNode(items[0]);
|
||||
node = Ext.get(node);
|
||||
node.scrollIntoView(this.el);
|
||||
}
|
||||
},
|
||||
dblclick: {
|
||||
fn: function() {
|
||||
this.fireEvent('naventer');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.onkeyup = function(e) {
|
||||
switch(e.keyCode) {
|
||||
this.addEvents(
|
||||
'navup',
|
||||
'navdown',
|
||||
'navleft',
|
||||
'navright',
|
||||
'navback',
|
||||
'naventer'
|
||||
);
|
||||
tv.ui.ChannelList.superclass.initComponent.apply(this, arguments);
|
||||
},
|
||||
|
||||
visibleItems: function() {
|
||||
var nodes = this.getNodes(0, 0);
|
||||
if(nodes.length == 0)
|
||||
return 0;
|
||||
|
||||
var height = this.getTemplateTarget().getHeight();
|
||||
var itemHeight = Ext.get(nodes[0]).getHeight()
|
||||
return Math.floor(height / itemHeight);
|
||||
},
|
||||
|
||||
onRender : function(ct, position) {
|
||||
tv.ui.ChannelList.superclass.onRender.call(this, ct, position);
|
||||
Ext.dd.ScrollManager.register(this.el);
|
||||
|
||||
this.getTemplateTarget().set({tabindex: Ext.id(undefined, '0')});
|
||||
this.getTemplateTarget().on('keydown', function(e) {
|
||||
switch(e.getKey()) {
|
||||
|
||||
case VK_LEFT:
|
||||
this.fireEvent('navleft');
|
||||
break;
|
||||
|
||||
case VK_RIGHT:
|
||||
this.fireEvent('navright');
|
||||
break;
|
||||
|
||||
case VK_UP:
|
||||
var max = tv.channels.getTotalCount() - 1;
|
||||
if(max < 0)
|
||||
return;
|
||||
|
||||
else if(currentChannel < max)
|
||||
currentChannel += 1;
|
||||
|
||||
else
|
||||
currentChannel = max;
|
||||
|
||||
ch = tv.channels.getAt(currentChannel);
|
||||
onChannelZap(ch.data);
|
||||
this.fireEvent('navup', 1);
|
||||
break;
|
||||
|
||||
case VK_DOWN:
|
||||
if(tv.channels.getTotalCount() == 0)
|
||||
return;
|
||||
|
||||
else if(currentChannel < 1)
|
||||
currentChannel = 0;
|
||||
|
||||
else
|
||||
currentChannel -= 1;
|
||||
|
||||
ch = tv.channels.getAt(currentChannel);
|
||||
onChannelZap(ch.data);
|
||||
this.fireEvent('navdown', 1);
|
||||
break;
|
||||
|
||||
case VK_PAGE_UP:
|
||||
var cnt = this.visibleItems();
|
||||
this.fireEvent('navup', cnt);
|
||||
break;
|
||||
|
||||
case VK_PAGE_DOWN:
|
||||
var cnt = this.visibleItems();
|
||||
this.fireEvent('navdown', cnt);
|
||||
break;
|
||||
|
||||
case VK_SPACE:
|
||||
case VK_ENTER:
|
||||
this.fireEvent('naventer');
|
||||
break;
|
||||
|
||||
case VK_BACKSPACE:
|
||||
case VK_ESCAPE:
|
||||
case VK_BACK:
|
||||
this.fireEvent('navback');
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var onChannelZap = function(ch) {
|
||||
var channelNameEl = document.getElementById('sb_channelName');
|
||||
channelNameEl.innerHTML = ch.name;
|
||||
e.stopEvent();
|
||||
return true;
|
||||
|
||||
var channelLogoEl = document.getElementById('sb_channelLogo');
|
||||
if(ch.ch_icon) {
|
||||
channelLogoEl.src = ch.ch_icon;
|
||||
channelLogoEl.style = '';
|
||||
} else {
|
||||
channelLogoEl.src = '';
|
||||
channelLogoEl.style = 'display: none';
|
||||
}
|
||||
|
||||
tv.epg.setBaseParam('channel', new String(ch.name));
|
||||
tv.epg.load();
|
||||
|
||||
var videoPlayer = document.getElementById('tv_videoPlayer');
|
||||
|
||||
setTimeout(function() {
|
||||
videoPlayer.src = tv.playback.getUrl(ch.chid);
|
||||
videoPlayer.load();
|
||||
videoPlayer.play();
|
||||
}, 1);
|
||||
}.bind(this));
|
||||
}
|
||||
});
|
||||
|
||||
var initDataStores = function() {
|
||||
tv.epg.on('load', function() {
|
||||
var nowTitle = document.getElementById('sb_nowTitle');
|
||||
var nowDuration = document.getElementById('sb_nowDuration');
|
||||
var nextTitle = document.getElementById('sb_nextTitle');
|
||||
var nextDuration = document.getElementById('sb_nextDuration');
|
||||
var event = undefined;
|
||||
|
||||
if(tv.epg.getTotalCount() < 1) {
|
||||
nowTitle.innerHTML = '';
|
||||
nowDuration.innerHTML = '';
|
||||
} else {
|
||||
event = tv.epg.getAt(0).data;
|
||||
nowTitle.innerHTML = event.title;
|
||||
nowDuration.innerHTML = event.start.toLocaleTimeString();
|
||||
}
|
||||
|
||||
if(tv.epg.getTotalCount() < 2) {
|
||||
nextTitle.innerHTML = '';
|
||||
nextDuration.innerHTML = '';
|
||||
} else {
|
||||
event = tv.epg.getAt(1).data;
|
||||
nextTitle.innerHTML = event.title;
|
||||
nextDuration.innerHTML = event.start.toLocaleTimeString();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// public space
|
||||
tv.app = function() {
|
||||
return {
|
||||
init: function() {
|
||||
initDataStores();
|
||||
initKeyboard();
|
||||
updateClock.delay(1);
|
||||
|
||||
var videoPlayer = new tv.ui.VideoPlayer({
|
||||
params: {
|
||||
resolution: 384
|
||||
},
|
||||
renderTo: Ext.getBody()
|
||||
});
|
||||
|
||||
var chList = new tv.ui.ChannelList({
|
||||
store: new Ext.data.JsonStore({
|
||||
autoLoad : true,
|
||||
root : 'entries',
|
||||
fields : ['ch_icon', 'number', 'name', 'chid'],
|
||||
id : 'chid',
|
||||
sortInfo : {
|
||||
field : 'number',
|
||||
direction : "ASC"
|
||||
},
|
||||
url : "../channels",
|
||||
baseParams : {
|
||||
op : 'list'
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
var chListPanel = new Ext.Panel({
|
||||
title:'Channels',
|
||||
items: chList,
|
||||
cls: 'tv-channel-list',
|
||||
renderTo: Ext.getBody()
|
||||
});
|
||||
|
||||
window.onresize = function() {
|
||||
var h = chListPanel.el.getHeight();
|
||||
h -= chListPanel.header.getHeight();
|
||||
h -= 25;
|
||||
|
||||
chList.setHeight(h);
|
||||
};
|
||||
|
||||
chListPanel.on('show', function() {
|
||||
window.onresize();
|
||||
});
|
||||
|
||||
chList.on('navback', function() {
|
||||
chListPanel.hide();
|
||||
chList.blur();
|
||||
});
|
||||
|
||||
chList.on('naventer', function() {
|
||||
var indices = this.getSelectedIndexes();
|
||||
if(indices.length == 0)
|
||||
return;
|
||||
|
||||
var item = this.store.getAt(indices[0]);
|
||||
|
||||
videoPlayer.zapTo(item.data.chid);
|
||||
chListPanel.hide();
|
||||
chList.blur();
|
||||
});
|
||||
|
||||
chList.on('navup', function(cnt) {
|
||||
var indices = chList.getSelectedIndexes();
|
||||
if(indices.length == 0)
|
||||
this.select(this.store.getTotalCount() - 1);
|
||||
else if(indices[0] - cnt >= 0)
|
||||
this.select(indices[0] - cnt);
|
||||
else
|
||||
this.select(0);
|
||||
});
|
||||
|
||||
chList.on('navdown', function(cnt) {
|
||||
var indices = chList.getSelectedIndexes();
|
||||
if(indices.length == 0)
|
||||
this.select(0);
|
||||
else if(indices[0] + cnt < this.store.getTotalCount())
|
||||
this.select(indices[0] + cnt);
|
||||
else
|
||||
this.select(this.store.getTotalCount() - 1);
|
||||
});
|
||||
|
||||
chList.on('navleft', function() {
|
||||
|
||||
});
|
||||
|
||||
chList.on('navright', function() {
|
||||
|
||||
});
|
||||
|
||||
var nav = new Ext.KeyNav(Ext.getDoc(), {
|
||||
'enter': function(e) {
|
||||
chListPanel.show();
|
||||
chList.focus();
|
||||
},
|
||||
'scope': this
|
||||
});
|
||||
|
||||
chListPanel.show();
|
||||
chList.focus();
|
||||
}
|
||||
};
|
||||
}(); // end of app
|
||||
|
|
Loading…
Add table
Reference in a new issue