tvheadend.acleditor = function() {
- var fm = Ext.form;
+ var fm = Ext.form;
- var cm = new Ext.grid.ColumnModel({
- defaultSortable: true,
+ var cm = new Ext.grid.ColumnModel({
+ defaultSortable: true,
+ columns: [{
+ xtype: 'checkcolumn',
+ header: "Enabled",
+ dataIndex: 'enabled',
+ width: 60
+ }, {
+ header: "Username",
+ dataIndex: 'username',
+ editor: new fm.TextField({
+ allowBlank: false
+ })
+ }, {
+ header: "Password",
+ dataIndex: 'password',
+ renderer: function(value, metadata, record, row, col, store) {
+ return '<span class="tvh-grid-unset">Hidden</span>';
+ },
+ editor: new fm.TextField({
+ allowBlank: false
+ })
+ }, {
+ header: "Prefix",
+ dataIndex: 'prefix',
+ editor: new fm.TextField({
+ allowBlank: false
+ })
+ }, {
+ xtype: 'checkcolumn',
+ header: "Streaming",
+ dataIndex: 'streaming',
+ width: 100
+ }, {
+ xtype: 'checkcolumn',
+ header: "Video Recorder",
+ dataIndex: 'dvr',
+ width: 100
+ }, {
+ xtype: 'checkcolumn',
+ header: "All Configs (VR)",
+ dataIndex: 'dvrallcfg',
+ width: 100
+ }, {
+ xtype: 'checkcolumn',
+ header: "Web Interface",
+ dataIndex: 'webui',
+ width: 100
+ }, {
+ xtype: 'checkcolumn',
+ header: "Admin",
+ dataIndex: 'admin',
+ width: 100
+ }, {
+ xtype: 'checkcolumn',
+ header: "Channel Tag Only",
+ dataIndex: 'tag_only',
+ width: 200
+ }, {
+ header: "Comment",
+ dataIndex: 'comment',
+ width: 300,
+ editor: new fm.TextField({})
+ }]});
- columns : [{
- xtype: 'checkcolumn',
- header : "Enabled",
- dataIndex : 'enabled',
- width : 60
- }, {
- header : "Username",
- dataIndex : 'username',
- editor : new fm.TextField({
- allowBlank : false
- })
- }, {
- header : "Password",
- dataIndex : 'password',
- renderer : function(value, metadata, record, row, col, store) {
- return '<span class="tvh-grid-unset">Hidden</span>';
- },
- editor : new fm.TextField({
- allowBlank : false
- })
- }, {
- header : "Prefix",
- dataIndex : 'prefix',
- editor : new fm.TextField({
- allowBlank : false
- })
- }, {
- xtype: 'checkcolumn',
- header : "Streaming",
- dataIndex : 'streaming',
- width : 100
- }, {
- xtype: 'checkcolumn',
- header : "Video Recorder",
- dataIndex : 'dvr',
- width : 100
- }, {
- xtype: 'checkcolumn',
- header : "All Configs (VR)",
- dataIndex : 'dvrallcfg',
- width : 100
- }, {
- xtype: 'checkcolumn',
- header : "Web Interface",
- dataIndex : 'webui',
- width : 100
- }, {
- xtype: 'checkcolumn',
- header : "Admin",
- dataIndex : 'admin',
- width : 100
- }, {
- xtype: 'checkcolumn',
- header : "Channel Tag Only",
- dataIndex : 'tag_only',
- width : 200
- }, {
- header : "Comment",
- dataIndex : 'comment',
- width : 300,
- editor : new fm.TextField({})
- }]});
+ var UserRecord = Ext.data.Record.create(
+ ['enabled', 'streaming', 'dvr', 'dvrallcfg', 'admin', 'webui', 'username', 'tag_only',
+ 'prefix', 'password', 'comment'
+ ]);
- var UserRecord = Ext.data.Record.create(
- [ 'enabled', 'streaming', 'dvr', 'dvrallcfg', 'admin', 'webui', 'username', 'tag_only',
- 'prefix', 'password', 'comment'
- ]);
-
- return new tvheadend.tableEditor('Access control', 'accesscontrol', cm,
- UserRecord, [], null, 'config_access.html',
- 'group');
-}
+ return new tvheadend.tableEditor('Access control', 'accesscontrol', cm,
+ UserRecord, [], null, 'config_access.html',
+ 'group');
+};
tvheadend.capmteditor = function() {
- var fm = Ext.form;
+ var fm = Ext.form;
- function setMetaAttr(meta, record) {
- var enabled = record.get('enabled');
- if (!enabled) return;
+ function setMetaAttr(meta, record) {
+ var enabled = record.get('enabled');
+ if (!enabled)
+ return;
- var connected = record.get('connected');
- if (connected == 2) {
- meta.attr = 'style="color:green;"';
- }
- else if (connected == 1) {
- meta.attr = 'style="color:orange;"';
- }
- else {
- meta.attr = 'style="color:red;"';
- }
- }
- var selectMode = new Ext.form.ComboBox({
- displayField:'name',
- valueField: 'res',
- value: 2,
- mode: 'local',
- editable: false,
- triggerAction: 'all',
- emptyText: 'Select mode...',
- store: new Ext.data.SimpleStore({
- fields: ['res','name'],
- id: 0,
- data: [
- ['2','Recent OSCam (svn rev >= 9095)'],
- ['1','Older OSCam'],
- ['0','Wrapper (capmt_ca.so)']
- ]
- })
- });
+ var connected = record.get('connected');
+ if (connected === 2) {
+ meta.attr = 'style="color:green;"';
+ }
+ else if (connected === 1) {
+ meta.attr = 'style="color:orange;"';
+ }
+ else {
+ meta.attr = 'style="color:red;"';
+ }
+ }
+ var selectMode = new Ext.form.ComboBox({
+ displayField: 'name',
+ valueField: 'res',
+ value: 2,
+ mode: 'local',
+ editable: false,
+ triggerAction: 'all',
+ emptyText: 'Select mode...',
+ store: new Ext.data.SimpleStore({
+ fields: ['res', 'name'],
+ id: 0,
+ data: [
+ ['2', 'Recent OSCam (svn rev >= 9095)'],
+ ['1', 'Older OSCam'],
+ ['0', 'Wrapper (capmt_ca.so)']
+ ]
+ })
+ });
- var cm = new Ext.grid.ColumnModel({
- defaultSortable: true,
- columns: [ {
- xtype: 'checkcolumn',
- header : "Enabled",
- dataIndex : 'enabled',
- width : 60
- }, {
- header: "Mode",
- dataIndex: 'oscam',
- width: 150,
- editor: selectMode
- }, {
- header : "Camd.socket Filename",
- dataIndex : 'camdfilename',
- width : 200,
- renderer : function(value, metadata, record, row, col, store) {
- setMetaAttr(metadata, record);
- return value;
- },
- editor : new fm.TextField({
- allowBlank : false
- })
- }, {
- header : "Listenport",
- dataIndex : 'port',
- renderer : function(value, metadata, record, row, col, store) {
- setMetaAttr(metadata, record);
- return value;
- },
- editor : new fm.TextField({
- allowBlank : false
- })
- }, {
- header : "Comment",
- dataIndex : 'comment',
- width : 400,
- renderer : function(value, metadata, record, row, col, store) {
- setMetaAttr(metadata, record);
- return value;
- },
- editor : new fm.TextField()
- } ]});
+ var cm = new Ext.grid.ColumnModel({
+ defaultSortable: true,
+ columns: [{
+ xtype: 'checkcolumn',
+ header: "Enabled",
+ dataIndex: 'enabled',
+ width: 60
+ }, {
+ header: "Mode",
+ dataIndex: 'oscam',
+ width: 150,
+ editor: selectMode
+ }, {
+ header: "Camd.socket Filename",
+ dataIndex: 'camdfilename',
+ width: 200,
+ renderer: function(value, metadata, record, row, col, store) {
+ setMetaAttr(metadata, record);
+ return value;
+ },
+ editor: new fm.TextField({
+ allowBlank: false
+ })
+ }, {
+ header: "Listenport",
+ dataIndex: 'port',
+ renderer: function(value, metadata, record, row, col, store) {
+ setMetaAttr(metadata, record);
+ return value;
+ },
+ editor: new fm.TextField({
+ allowBlank: false
+ })
+ }, {
+ header: "Comment",
+ dataIndex: 'comment',
+ width: 400,
+ renderer: function(value, metadata, record, row, col, store) {
+ setMetaAttr(metadata, record);
+ return value;
+ },
+ editor: new fm.TextField()
+ }]});
- var rec = Ext.data.Record.create([ 'enabled', 'connected', 'camdfilename',
- 'port', 'oscam', 'comment' ]);
+ var rec = Ext.data.Record.create(['enabled', 'connected', 'camdfilename',
+ 'port', 'oscam', 'comment']);
- store = new Ext.data.JsonStore({
- root : 'entries',
- fields : rec,
- url : "tablemgr",
- autoLoad : true,
- id : 'id',
- baseParams : {
- table : 'capmt',
- op : "get"
- }
- });
+ store = new Ext.data.JsonStore({
+ root: 'entries',
+ fields: rec,
+ url: "tablemgr",
+ autoLoad: true,
+ id: 'id',
+ baseParams: {
+ table: 'capmt',
+ op: "get"
+ }
+ });
- tvheadend.comet.on('capmt', function(server) {
- var rec = store.getById(server.id);
- if (rec) {
- rec.set('connected', server.connected);
- }
- });
+ tvheadend.comet.on('capmt', function(server) {
+ var rec = store.getById(server.id);
+ if (rec) {
+ rec.set('connected', server.connected);
+ }
+ });
- return new tvheadend.tableEditor('Capmt Connections', 'capmt', cm, rec,
- [ ], store, 'config_capmt.html', 'key');
-}
+ return new tvheadend.tableEditor('Capmt Connections', 'capmt', cm, rec,
+ [], store, 'config_capmt.html', 'key');
+};
* Channel tags
*/
tvheadend.channelTags = new Ext.data.JsonStore({
- autoLoad : true,
- root : 'entries',
- fields : [ 'identifier', 'name' ],
- id : 'identifier',
- url : 'channeltags',
- baseParams : {
- op : 'listTags'
- }
+ autoLoad: true,
+ root: 'entries',
+ fields: ['identifier', 'name'],
+ id: 'identifier',
+ url: 'channeltags',
+ baseParams: {
+ op: 'listTags'
+ }
});
tvheadend.channelTags.setDefaultSort('name', 'ASC');
tvheadend.comet.on('channeltags', function(m) {
- if (m.reload != null) tvheadend.channelTags.reload();
+ if (m.reload != null)
+ tvheadend.channelTags.reload();
});
/**
* Channels
*/
tvheadend.channelrec = new Ext.data.Record.create(
- [ 'name', 'chid', 'epggrabsrc', 'tags', 'ch_icon', 'epg_pre_start',
- 'epg_post_end', 'number' ]);
+ ['name', 'chid', 'epggrabsrc', 'tags', 'ch_icon', 'epg_pre_start',
+ 'epg_post_end', 'number']);
tvheadend.channels = new Ext.data.JsonStore({
- url : 'api/channel/list',
- root : 'entries',
- fields : [ 'key', 'val' ],
- id : 'key',
- autoLoad : true,
- sortInfo : {
- field : 'val',
- direction : 'ASC'
- }
+ url: 'api/channel/list',
+ root: 'entries',
+ fields: ['key', 'val'],
+ id: 'key',
+ autoLoad: true,
+ sortInfo: {
+ field: 'val',
+ direction: 'ASC'
+ }
});
tvheadend.comet.on('channels', function(m) {
- if (m.reload != null) tvheadend.channels.reload();
+ if (m.reload != null)
+ tvheadend.channels.reload();
});
tvheadend.channel_tab = function(panel)
{
- function assign_low_number() {
- var tab = panel.getActiveTab()
- var sm = tab.getSelectionModel()
- var store = tab.getStore()
-
- if (sm.getCount() != 1)
- return
-
- var nums = []
- store.each(function() {
- if(this.data.number > 0)
- nums.push(this.data.number)
- })
-
- if(nums.length == 0)
- {
- sm.getSelected().set('number', 1)
- return
- }
+ function assign_low_number() {
+ var tab = panel.getActiveTab();
+ var sm = tab.getSelectionModel();
+ var store = tab.getStore();
- nums.sort(function(a,b) { return (a - b) })
+ if (sm.getCount() !== 1)
+ return;
- var max = nums[nums.length - 1]
- var low = max + 1
+ var nums = [];
+ store.each(function() {
+ if (this.data.number > 0)
+ nums.push(this.data.number);
+ });
- for(var i = 1; i <= max; ++i)
- {
- var ct = false
- for(var j = 0; j < nums.length; ++j)
- if(nums[j] == i)
+ if (nums.length === 0)
{
- ct = true
- break
+ sm.getSelected().set('number', 1);
+ return;
}
- if(!ct)
- {
- low = i
- break;
- }
- }
+ nums.sort(function(a, b) {
+ return (a - b);
+ });
- sm.getSelected().set('number', low)
- sm.selectNext()
- }
-
- function move_number_up() {
- var tab = panel.getActiveTab()
- var sm = tab.getSelectionModel()
- var store = tab.getStore()
-
- if (sm.getCount() != 1)
- return
-
- var sel = sm.getSelected()
- var num = sel.data.number
-
- if(!num)
- num = 0
-
- store.each(function() {
- if(this.data.number == num + 1)
- this.set('number', num)
- })
-
- sel.set('number', num + 1)
- }
-
- function move_number_down() {
- var tab = panel.getActiveTab()
- var sm = tab.getSelectionModel()
- var store = tab.getStore()
-
- if(sm.getCount() != 1)
- return
-
- var sel = sm.getSelected()
- var num = sel.data.number
-
- if(!num)
- num = 0
-
- if(num <= 1)
- return
-
- store.each(function() {
- if(this.data.number == num - 1)
- this.set('number', num)
- })
-
- sel.set('number', num - 1)
- }
-
- function swap_numbers() {
- var tab = panel.getActiveTab()
- var sm = tab.getSelectionModel()
- var store = tab.getStore()
-
- if(sm.getCount() != 2)
- return
-
- var sel = sm.getSelections()
- var tmp = sel[0].data.number
-
- sel[0].set('number', sel[1].data.number)
- sel[1].set('number', tmp)
- }
-
- var mapButton = new Ext.Toolbar.Button({
- tooltip : 'Map services to channels',
- iconCls : 'clone',
- text : 'Map Services',
- handler : tvheadend.service_mapper,
- disabled : false
- });
-
- var lowNoButton = new Ext.Toolbar.Button({
- tooltip : 'Assign lowest free channel number',
- iconCls : 'bullet_add',
- text : 'Assign Number',
- handler : assign_low_number,
- disabled : false
- });
-
- var noUpButton = new Ext.Toolbar.Button({
- tooltip : 'Move channel one number up',
- iconCls : 'arrow_up',
- text : 'Number Up',
- handler : move_number_up,
- disabled : false
- });
-
- var noDownButton = new Ext.Toolbar.Button({
- tooltip : 'Move channel one number down',
- iconCls : 'arrow_down',
- text : 'Number Down',
- handler : move_number_down,
- disabled : false
- });
-
- var noSwapButton = new Ext.Toolbar.Button({
- tooltip : 'Swap the two selected channels numbers',
- iconCls : 'arrow_switch',
- text : 'Swap Numbers',
- handler : swap_numbers,
- disabled : false
- });
-
- tvheadend.idnode_grid(panel, {
- url : 'api/channel',
- comet : 'channel',
- titleS : 'Channel',
- titleP : 'Channels',
- tabIndex: 0,
- add : {
- url : 'api/channel',
- create : {}
- },
- del : true,
- tbar : [ mapButton, lowNoButton, noUpButton, noDownButton, noSwapButton ],
- lcol : [
- {
- width : 50,
- header : 'Play',
- renderer : function (v, o, r) {
- return "<a href='stream/channel/" + r.id + "'>Play</a>";
+ var max = nums[nums.length - 1];
+ var low = max + 1;
+
+ for (var i = 1; i <= max; ++i)
+ {
+ var ct = false;
+ for (var j = 0; j < nums.length; ++j)
+ if (nums[j] === i)
+ {
+ ct = true;
+ break
+ }
+ if (!ct)
+ {
+ low = i;
+ break;
+ }
}
- }
- ],
- sort : {
- field : 'number',
- direction : 'ASC'
+
+ sm.getSelected().set('number', low);
+ sm.selectNext();
}
- });
-}
+
+ function move_number_up() {
+ var tab = panel.getActiveTab();
+ var sm = tab.getSelectionModel();
+ var store = tab.getStore();
+
+ if (sm.getCount() !== 1)
+ return;
+
+ var sel = sm.getSelected();
+ var num = sel.data.number;
+
+ if (!num)
+ num = 0;
+
+ store.each(function() {
+ if (this.data.number === num + 1)
+ this.set('number', num);
+ });
+
+ sel.set('number', num + 1);
+ }
+
+ function move_number_down() {
+ var tab = panel.getActiveTab();
+ var sm = tab.getSelectionModel();
+ var store = tab.getStore();
+
+ if (sm.getCount() !== 1)
+ return;
+
+ var sel = sm.getSelected();
+ var num = sel.data.number;
+
+ if (!num)
+ num = 0;
+
+ if (num <= 1)
+ return;
+
+ store.each(function() {
+ if (this.data.number === num - 1)
+ this.set('number', num);
+ });
+
+ sel.set('number', num - 1);
+ }
+
+ function swap_numbers() {
+ var tab = panel.getActiveTab();
+ var sm = tab.getSelectionModel();
+ var store = tab.getStore(); //store is unused
+
+ if (sm.getCount() !== 2)
+ return;
+
+ var sel = sm.getSelections();
+ var tmp = sel[0].data.number;
+
+ sel[0].set('number', sel[1].data.number);
+ sel[1].set('number', tmp);
+ }
+
+ var mapButton = new Ext.Toolbar.Button({
+ tooltip: 'Map services to channels',
+ iconCls: 'clone',
+ text: 'Map Services',
+ handler: tvheadend.service_mapper,
+ disabled: false
+ });
+
+ var lowNoButton = new Ext.Toolbar.Button({
+ tooltip: 'Assign lowest free channel number',
+ iconCls: 'bullet_add',
+ text: 'Assign Number',
+ handler: assign_low_number,
+ disabled: false
+ });
+
+ var noUpButton = new Ext.Toolbar.Button({
+ tooltip: 'Move channel one number up',
+ iconCls: 'arrow_up',
+ text: 'Number Up',
+ handler: move_number_up,
+ disabled: false
+ });
+
+ var noDownButton = new Ext.Toolbar.Button({
+ tooltip: 'Move channel one number down',
+ iconCls: 'arrow_down',
+ text: 'Number Down',
+ handler: move_number_down,
+ disabled: false
+ });
+
+ var noSwapButton = new Ext.Toolbar.Button({
+ tooltip: 'Swap the two selected channels numbers',
+ iconCls: 'arrow_switch',
+ text: 'Swap Numbers',
+ handler: swap_numbers,
+ disabled: false
+ });
+
+ tvheadend.idnode_grid(panel, {
+ url: 'api/channel',
+ comet: 'channel',
+ titleS: 'Channel',
+ titleP: 'Channels',
+ tabIndex: 0,
+ add: {
+ url: 'api/channel',
+ create: {}
+ },
+ del: true,
+ tbar: [mapButton, lowNoButton, noUpButton, noDownButton, noSwapButton],
+ lcol: [
+ {
+ width: 50,
+ header: 'Play',
+ renderer: function(v, o, r) {
+ return "<a href='stream/channel/" + r.id + "'>Play</a>";
+ }
+ }
+ ],
+ sort: {
+ field: 'number',
+ direction: 'ASC'
+ }
+ });
+};
* Comet interfaces
*/
Ext.extend(tvheadend.Comet = function() {
- this.addEvents({
- accessUpdate : true,
- tvAdapter : true,
- dvbMux : true,
- dvbStore : true,
- dvbSatConf : true,
- logmessage : true,
- channeltags : true,
- autorec : true,
- dvrdb : true,
- dvrconfig : true,
- channels : true
- });
+ this.addEvents({
+ accessUpdate: true,
+ tvAdapter: true,
+ dvbMux: true,
+ dvbStore: true,
+ dvbSatConf: true,
+ logmessage: true,
+ channeltags: true,
+ autorec: true,
+ dvrdb: true,
+ dvrconfig: true,
+ channels: true
+ });
}, Ext.util.Observable);
tvheadend.comet = new tvheadend.Comet();
tvheadend.cometPoller = function() {
- var failures = 0;
+ var failures = 0;
- var cometRequest = new Ext.util.DelayedTask(function() {
+ var cometRequest = new Ext.util.DelayedTask(function() {
- Ext.Ajax
- .request({
- url : 'comet/poll',
- params : {
- boxid : (tvheadend.boxid ? tvheadend.boxid : null),
- immediate : failures > 0 ? 1 : 0
- },
- success : function(result, request) {
- parse_comet_response(result.responseText);
+ Ext.Ajax
+ .request({
+ url: 'comet/poll',
+ params: {
+ boxid: (tvheadend.boxid ? tvheadend.boxid : null),
+ immediate: failures > 0 ? 1 : 0
+ },
+ success: function(result, request) {
+ parse_comet_response(result.responseText);
- if (failures > 1) {
- tvheadend.log('Reconnected to Tvheadend',
- 'font-weight: bold; color: #080');
- }
- failures = 0;
- },
- failure : function(result, request) {
- cometRequest.delay(failures ? 1000 : 1);
- if (failures == 1) {
- tvheadend.log('There seems to be a problem with the '
- + 'live update feed from Tvheadend. '
- + 'Trying to reconnect...',
- 'font-weight: bold; color: #f00');
- }
- failures++;
- }
- });
- });
+ if (failures > 1) {
+ tvheadend.log('Reconnected to Tvheadend',
+ 'font-weight: bold; color: #080');
+ }
+ failures = 0;
+ },
+ failure: function(result, request) {
+ cometRequest.delay(failures ? 1000 : 1);
+ if (failures === 1) {
+ tvheadend.log('There seems to be a problem with the '
+ + 'live update feed from Tvheadend. '
+ + 'Trying to reconnect...',
+ 'font-weight: bold; color: #f00');
+ }
+ failures++;
+ }
+ });
+ });
- function parse_comet_response(responsetxt) {
- response = Ext.util.JSON.decode(responsetxt);
- tvheadend.boxid = response.boxid
- for (x = 0; x < response.messages.length; x++) {
- m = response.messages[x];
- try {
- tvheadend.comet.fireEvent(m.notificationClass, m);
- } catch (e) {
- tvheadend.log('comet failure [e=' + e.message + ']');
- }
- }
- cometRequest.delay(100);
- }
- ;
+ function parse_comet_response(responsetxt) {
+ response = Ext.util.JSON.decode(responsetxt);
+ tvheadend.boxid = response.boxid;
+ for (x = 0; x < response.messages.length; x++) {
+ m = response.messages[x];
+ try {
+ tvheadend.comet.fireEvent(m.notificationClass, m);
+ } catch (e) {
+ tvheadend.log('comet failure [e=' + e.message + ']');
+ }
+ }
+ cometRequest.delay(100);
+ }
+ ;
- cometRequest.delay(100);
-}
+ cometRequest.delay(100);
+};
// Store: config languages
tvheadend.languages = new Ext.data.JsonStore({
- autoLoad:true,
- root:'entries',
- fields: ['identifier','name'],
+ autoLoad: true,
+ root: 'entries',
+ fields: ['identifier', 'name'],
id: 'identifier',
- url:'languages',
+ url: 'languages',
baseParams: {
- op: 'list'
+ op: 'list'
}
});
// Store: all languages
tvheadend.config_languages = new Ext.data.JsonStore({
- autoLoad:true,
- root:'entries',
- fields: ['identifier','name'],
+ autoLoad: true,
+ root: 'entries',
+ fields: ['identifier', 'name'],
id: 'identifier',
- url:'languages',
+ url: 'languages',
baseParams: {
- op: 'config'
+ op: 'config'
}
});
tvheadend.languages.setDefaultSort('name', 'ASC');
tvheadend.comet.on('config', function(m) {
- if(m.reload != null) {
+ if (m.reload != null) {
tvheadend.languages.reload();
tvheadend.config_languages.reload();
}
tvheadend.miscconf = function() {
- /*
- * Basic Config
- */
- var confreader = new Ext.data.JsonReader({
- root : 'config'
- }, [ 'muxconfpath', 'language',
- 'tvhtime_update_enabled', 'tvhtime_ntp_enabled',
- 'tvhtime_tolerance', 'transcoding_enabled']);
-
- /* ****************************************************************
- * Form Fields
- * ***************************************************************/
-
- /*
- * DVB path
- */
-
- var dvbscanPath = new Ext.form.TextField({
- fieldLabel : 'DVB scan files path',
- name : 'muxconfpath',
- allowBlank : true,
- width: 400
- });
-
- /*
- * Language
- */
-
- var language = new Ext.ux.ItemSelector({
- name: 'language',
- fromStore: tvheadend.languages,
- toStore: tvheadend.config_languages,
- fieldLabel: 'Default Language(s)',
- dataFields:['identifier', 'name'],
- msWidth: 190,
- msHeight: 150,
- valueField: 'identifier',
- displayField: 'name',
- imagePath: 'static/multiselect/resources',
- toLegend: 'Selected',
- fromLegend: 'Available'
- });
-
- /*
- * Time/Date
- */
- var tvhtimeUpdateEnabled = new Ext.form.Checkbox({
- name: 'tvhtime_update_enabled',
- fieldLabel: 'Update time'
- });
-
- var tvhtimeNtpEnabled = new Ext.form.Checkbox({
- name: 'tvhtime_ntp_enabled',
- fieldLabel: 'Enable NTP driver'
- });
-
- var tvhtimeTolerance = new Ext.form.NumberField({
- name: 'tvhtime_tolerance',
- fieldLabel: 'Update tolerance (ms)'
- });
-
- var tvhtimePanel = new Ext.form.FieldSet({
- title: 'Time Update',
- width: 700,
- autoHeight: true,
- collapsible: true,
- items : [ tvhtimeUpdateEnabled, tvhtimeNtpEnabled, tvhtimeTolerance ]
- });
-
- /*
- * Image cache
- */
- if (tvheadend.capabilities.indexOf('imagecache') != -1) {
- var imagecache_reader = new Ext.data.JsonReader({
- root : 'entries'
+ /*
+ * Basic Config
+ */
+ var confreader = new Ext.data.JsonReader({
+ root: 'config'
},
[
- 'enabled', 'ok_period', 'fail_period', 'ignore_sslcert',
+ 'muxconfpath', 'language',
+ 'tvhtime_update_enabled', 'tvhtime_ntp_enabled',
+ 'tvhtime_tolerance', 'transcoding_enabled'
]);
- var imagecacheEnabled = new Ext.ux.form.XCheckbox({
- name: 'enabled',
- fieldLabel: 'Enabled',
+ /* ****************************************************************
+ * Form Fields
+ * ***************************************************************/
+
+ /*
+ * DVB path
+ */
+
+ var dvbscanPath = new Ext.form.TextField({
+ fieldLabel: 'DVB scan files path',
+ name: 'muxconfpath',
+ allowBlank: true,
+ width: 400
});
- var imagecacheOkPeriod = new Ext.form.NumberField({
- name: 'ok_period',
- fieldLabel: 'Re-fetch period (hours)'
+ /*
+ * Language
+ */
+
+ var language = new Ext.ux.ItemSelector({
+ name: 'language',
+ fromStore: tvheadend.languages,
+ toStore: tvheadend.config_languages,
+ fieldLabel: 'Default Language(s)',
+ dataFields: ['identifier', 'name'],
+ msWidth: 190,
+ msHeight: 150,
+ valueField: 'identifier',
+ displayField: 'name',
+ imagePath: 'static/multiselect/resources',
+ toLegend: 'Selected',
+ fromLegend: 'Available'
});
- var imagecacheFailPeriod = new Ext.form.NumberField({
- name: 'fail_period',
- fieldLabel: 'Re-try period (hours)',
+ /*
+ * Time/Date
+ */
+ var tvhtimeUpdateEnabled = new Ext.form.Checkbox({
+ name: 'tvhtime_update_enabled',
+ fieldLabel: 'Update time'
});
- var imagecacheIgnoreSSLCert = new Ext.ux.form.XCheckbox({
- name: 'ignore_sslcert',
- fieldLabel: 'Ignore invalid SSL certificate'
+ var tvhtimeNtpEnabled = new Ext.form.Checkbox({
+ name: 'tvhtime_ntp_enabled',
+ fieldLabel: 'Enable NTP driver'
});
- var imagecachePanel = new Ext.form.FieldSet({
- title: 'Image Caching',
- width: 700,
- autoHeight: true,
- collapsible: true,
- items : [ imagecacheEnabled, imagecacheOkPeriod, imagecacheFailPeriod,
- imagecacheIgnoreSSLCert ]
+ var tvhtimeTolerance = new Ext.form.NumberField({
+ name: 'tvhtime_tolerance',
+ fieldLabel: 'Update tolerance (ms)'
});
- var imagecache_form = new Ext.form.FormPanel({
- border : false,
- labelAlign : 'left',
- labelWidth : 200,
- waitMsgTarget : true,
- reader: imagecache_reader,
- layout : 'form',
- defaultType : 'textfield',
- autoHeight : true,
- items : [ imagecachePanel ]
+ var tvhtimePanel = new Ext.form.FieldSet({
+ title: 'Time Update',
+ width: 700,
+ autoHeight: true,
+ collapsible: true,
+ items: [tvhtimeUpdateEnabled, tvhtimeNtpEnabled, tvhtimeTolerance]
});
- } else {
- var imagecache_form = null;
- }
-
- /*
- * Transcoding
- */
- var transcodingEnabled = new Ext.form.Checkbox({
- name: 'transcoding_enabled',
- fieldLabel: 'Enabled',
- });
-
- var transcodingPanel = new Ext.form.FieldSet({
- title: 'Transcoding',
- width: 700,
- autoHeight: true,
- collapsible: true,
- items : [ transcodingEnabled ]
- });
- if (tvheadend.capabilities.indexOf('transcoding') == -1)
- transcodingPanel.hide();
-
-
- /* ****************************************************************
- * Form
- * ***************************************************************/
-
- var saveButton = new Ext.Button({
- text : "Save configuration",
- tooltip : 'Save changes made to configuration below',
- iconCls : 'save',
- handler : saveChanges
- });
-
- var helpButton = new Ext.Button({
- text : 'Help',
- handler : function() {
- new tvheadend.help('General Configuration', 'config_misc.html');
- }
- });
-
- var confpanel = new Ext.form.FormPanel({
- labelAlign : 'left',
- labelWidth : 200,
- border : false,
- waitMsgTarget : true,
- reader : confreader,
- layout : 'form',
- defaultType : 'textfield',
- autoHeight : true,
- items : [ language, dvbscanPath,
- tvhtimePanel,
- transcodingPanel]
- });
-
- var _items = [confpanel];
- if (imagecache_form)
- _items.push(imagecache_form);
- var panel = new Ext.Panel({
- title : 'General',
- iconCls : 'wrench',
- border : false,
- bodyStyle : 'padding:15px',
- layout : 'form',
- items: _items,
- tbar : [ saveButton, '->', helpButton ]
- });
-
- /* ****************************************************************
- * Load/Save
- * ***************************************************************/
-
- confpanel.on('render', function() {
- confpanel.getForm().load({
- url : 'config',
- params : {
- op : 'loadSettings'
- },
- success : function(form, action) {
- confpanel.enable();
- }
- });
- if (imagecache_form)
- imagecache_form.getForm().load({
- url : 'api/imagecache/config/load',
- success : function (form, action) {
- imagecache_form.enable();
+
+ /*
+ * Image cache
+ */
+ if (tvheadend.capabilities.indexOf('imagecache') !== -1) {
+ var imagecache_reader = new Ext.data.JsonReader({
+ root: 'entries'
},
- failure : function (form, action) {
- alert("FAILED");
- }
- });
- });
-
- function saveChanges() {
- confpanel.getForm().submit({
- url : 'config',
- params : {
- op : 'saveSettings'
- },
- waitMsg : 'Saving Data...',
- failure : function(form, action) {
- Ext.Msg.alert('Save failed', action.result.errormsg);
- }
- });
- if (imagecache_form)
- imagecache_form.getForm().submit({
- url : 'api/imagecache/config/save',
- waitMsg : 'Saving data...',
- failure : function(form, action) {
- Ext.Msg.alert('Imagecache save failed', action.result.errormsg);
+ [
+ 'enabled', 'ok_period', 'fail_period', 'ignore_sslcert'
+ ]);
+
+ var imagecacheEnabled = new Ext.ux.form.XCheckbox({
+ name: 'enabled',
+ fieldLabel: 'Enabled'
+ });
+
+ var imagecacheOkPeriod = new Ext.form.NumberField({
+ name: 'ok_period',
+ fieldLabel: 'Re-fetch period (hours)'
+ });
+
+ var imagecacheFailPeriod = new Ext.form.NumberField({
+ name: 'fail_period',
+ fieldLabel: 'Re-try period (hours)'
+ });
+
+ var imagecacheIgnoreSSLCert = new Ext.ux.form.XCheckbox({
+ name: 'ignore_sslcert',
+ fieldLabel: 'Ignore invalid SSL certificate'
+ });
+
+ var imagecachePanel = new Ext.form.FieldSet({
+ title: 'Image Caching',
+ width: 700,
+ autoHeight: true,
+ collapsible: true,
+ items: [imagecacheEnabled, imagecacheOkPeriod, imagecacheFailPeriod,
+ imagecacheIgnoreSSLCert]
+ });
+
+ var imagecache_form = new Ext.form.FormPanel({
+ border: false,
+ labelAlign: 'left',
+ labelWidth: 200,
+ waitMsgTarget: true,
+ reader: imagecache_reader,
+ layout: 'form',
+ defaultType: 'textfield',
+ autoHeight: true,
+ items: [imagecachePanel]
+ });
+ } else {
+ var imagecache_form = null;
+ }
+
+ /*
+ * Transcoding
+ */
+ var transcodingEnabled = new Ext.form.Checkbox({
+ name: 'transcoding_enabled',
+ fieldLabel: 'Enabled'
+ });
+
+ var transcodingPanel = new Ext.form.FieldSet({
+ title: 'Transcoding',
+ width: 700,
+ autoHeight: true,
+ collapsible: true,
+ items: [transcodingEnabled]
+ });
+ if (tvheadend.capabilities.indexOf('transcoding') === -1)
+ transcodingPanel.hide();
+
+
+ /* ****************************************************************
+ * Form
+ * ***************************************************************/
+
+ var saveButton = new Ext.Button({
+ text: "Save configuration",
+ tooltip: 'Save changes made to configuration below',
+ iconCls: 'save',
+ handler: saveChanges
+ });
+
+ var helpButton = new Ext.Button({
+ text: 'Help',
+ handler: function() {
+ new tvheadend.help('General Configuration', 'config_misc.html');
}
- });
- }
+ });
+
+ var confpanel = new Ext.form.FormPanel({
+ labelAlign: 'left',
+ labelWidth: 200,
+ border: false,
+ waitMsgTarget: true,
+ reader: confreader,
+ layout: 'form',
+ defaultType: 'textfield',
+ autoHeight: true,
+ items: [language, dvbscanPath,
+ tvhtimePanel,
+ transcodingPanel]
+ });
+
+ var _items = [confpanel];
+ if (imagecache_form)
+ _items.push(imagecache_form);
+ var panel = new Ext.Panel({
+ title: 'General',
+ iconCls: 'wrench',
+ border: false,
+ bodyStyle: 'padding:15px',
+ layout: 'form',
+ items: _items,
+ tbar: [saveButton, '->', helpButton]
+ });
+
+ /* ****************************************************************
+ * Load/Save
+ * ***************************************************************/
+
+ confpanel.on('render', function() {
+ confpanel.getForm().load({
+ url: 'config',
+ params: {
+ op: 'loadSettings'
+ },
+ success: function(form, action) {
+ confpanel.enable();
+ }
+ });
+ if (imagecache_form)
+ imagecache_form.getForm().load({
+ url: 'api/imagecache/config/load',
+ success: function(form, action) {
+ imagecache_form.enable();
+ },
+ failure: function(form, action) {
+ alert("FAILED");
+ }
+ });
+ });
+
+ function saveChanges() {
+ confpanel.getForm().submit({
+ url: 'config',
+ params: {
+ op: 'saveSettings'
+ },
+ waitMsg: 'Saving Data...',
+ failure: function(form, action) {
+ Ext.Msg.alert('Save failed', action.result.errormsg);
+ }
+ });
+ if (imagecache_form)
+ imagecache_form.getForm().submit({
+ url: 'api/imagecache/config/save',
+ waitMsg: 'Saving data...',
+ failure: function(form, action) {
+ Ext.Msg.alert('Imagecache save failed', action.result.errormsg);
+ }
+ });
+ }
- return panel;
-}
+ return panel;
+};
tvheadend.cteditor = function() {
- var fm = Ext.form;
+ var fm = Ext.form;
+ var cm = new Ext.grid.ColumnModel({
+ defaultSortable: true,
+ columns: [{
+ xtype: 'checkcolumn',
+ header: "Enabled",
+ dataIndex: 'enabled',
+ width: 60
+ }, {
+ header: "Name",
+ dataIndex: 'name',
+ editor: new fm.TextField({
+ allowBlank: false
+ })
+ }, {
+ xtype: 'checkcolumn',
+ header: "Internal",
+ dataIndex: 'internal',
+ width: 100
+ }, {
+ header: "Icon (full URL)",
+ dataIndex: 'icon',
+ width: 400,
+ editor: new fm.TextField({})
+ }, {
+ xtype: 'checkcolumn',
+ header: "Icon has title",
+ dataIndex: 'titledIcon',
+ width: 100,
+ tooltip: 'Set this if the supplied icon has a title embedded. '
+ + 'This will tell displaying application not to superimpose title '
+ + 'on top of logo.'
+ }, {
+ header: "Comment",
+ dataIndex: 'comment',
+ width: 400,
+ editor: new fm.TextField({})
+ }]});
- var cm = new Ext.grid.ColumnModel({
- defaultSortable: true,
- columns : [{
- xtype: 'checkcolumn',
- header : "Enabled",
- dataIndex : 'enabled',
- width : 60
- } , {
- header : "Name",
- dataIndex : 'name',
- editor : new fm.TextField({
- allowBlank : false
- })
- }, {
- xtype: 'checkcolumn',
- header : "Internal",
- dataIndex : 'internal',
- width : 100
- }, {
- header : "Icon (full URL)",
- dataIndex : 'icon',
- width : 400,
- editor : new fm.TextField({})
- }, {
- xtype: 'checkcolumn',
- header : "Icon has title",
- dataIndex : 'titledIcon',
- width : 100,
- tooltip : 'Set this if the supplied icon has a title embedded. '
- + 'This will tell displaying application not to superimpose title '
- + 'on top of logo.'
- }, {
- header : "Comment",
- dataIndex : 'comment',
- width : 400,
- editor : new fm.TextField({})
- } ]});
+ var ChannelTagRecord = Ext.data.Record.create([
+ 'enabled', 'name', 'internal', 'icon', 'comment', 'titledIcon']);
- var ChannelTagRecord = Ext.data.Record.create([
- 'enabled', 'name', 'internal', 'icon', 'comment', 'titledIcon' ]);
-
- return new tvheadend.tableEditor('Channel Tags', 'channeltags', cm,
- ChannelTagRecord, [],
- null, 'config_tags.html', 'tags');
-}
+ return new tvheadend.tableEditor('Channel Tags', 'channeltags', cm,
+ ChannelTagRecord, [],
+ null, 'config_tags.html', 'tags');
+};
tvheadend.cwceditor = function() {
- var fm = Ext.form;
+ var fm = Ext.form;
- function setMetaAttr(meta, record) {
- var enabled = record.get('enabled');
- if (!enabled) return;
+ function setMetaAttr(meta, record) {
+ var enabled = record.get('enabled');
+ if (!enabled)
+ return;
- var connected = record.get('connected');
- if (connected == 1) {
- meta.attr = 'style="color:green;"';
- }
- else {
- meta.attr = 'style="color:red;"';
- }
- }
+ var connected = record.get('connected');
+ if (connected === 1) {
+ meta.attr = 'style="color:green;"';
+ }
+ else {
+ meta.attr = 'style="color:red;"';
+ }
+ }
- var cm = new Ext.grid.ColumnModel({
- defaultSortable: true,
- columns : [ {
- xtype: 'checkcolumn',
- header : "Enabled",
- dataIndex : 'enabled',
- width : 60
- }, {
- header : "Hostname",
- dataIndex : 'hostname',
- width : 200,
- renderer : function(value, metadata, record, row, col, store) {
- setMetaAttr(metadata, record);
- return value;
- },
- editor : new fm.TextField({
- allowBlank : false
- })
- }, {
- header : "Port",
- dataIndex : 'port',
- renderer : function(value, metadata, record, row, col, store) {
- setMetaAttr(metadata, record);
- return value;
- },
- editor : new fm.TextField({
- allowBlank : false
- })
- }, {
- header : "Username",
- dataIndex : 'username',
- renderer : function(value, metadata, record, row, col, store) {
- setMetaAttr(metadata, record);
- return value;
- },
- editor : new fm.TextField({
- allowBlank : false
- })
- }, {
- header : "Password",
- dataIndex : 'password',
- renderer : function(value, metadata, record, row, col, store) {
- setMetaAttr(metadata, record);
- return '<span class="tvh-grid-unset">Hidden</span>';
- },
- editor : new fm.TextField({
- allowBlank : false
- })
- }, {
- header : "DES Key",
- dataIndex : 'deskey',
- width : 300,
- renderer : function(value, metadata, record, row, col, store) {
- setMetaAttr(metadata, record);
- return '<span class="tvh-grid-unset">Hidden</span>';
- },
- editor : new fm.TextField({
- allowBlank : false
- })
- }, {
- xtype: 'checkcolumn',
- header : "Update Card",
- dataIndex : 'emm',
- width : 100
- }, {
- xtype: 'checkcolumn',
- header : "Update One",
- dataIndex : 'emmex',
- width : 100
- }, {
- header : "Comment",
- dataIndex : 'comment',
- width : 400,
- renderer : function(value, metadata, record, row, col, store) {
- setMetaAttr(metadata, record);
- return value;
- },
- editor : new fm.TextField()
- } ]});
+ var cm = new Ext.grid.ColumnModel({
+ defaultSortable: true,
+ columns: [{
+ xtype: 'checkcolumn',
+ header: "Enabled",
+ dataIndex: 'enabled',
+ width: 60
+ }, {
+ header: "Hostname",
+ dataIndex: 'hostname',
+ width: 200,
+ renderer: function(value, metadata, record, row, col, store) {
+ setMetaAttr(metadata, record);
+ return value;
+ },
+ editor: new fm.TextField({
+ allowBlank: false
+ })
+ }, {
+ header: "Port",
+ dataIndex: 'port',
+ renderer: function(value, metadata, record, row, col, store) {
+ setMetaAttr(metadata, record);
+ return value;
+ },
+ editor: new fm.TextField({
+ allowBlank: false
+ })
+ }, {
+ header: "Username",
+ dataIndex: 'username',
+ renderer: function(value, metadata, record, row, col, store) {
+ setMetaAttr(metadata, record);
+ return value;
+ },
+ editor: new fm.TextField({
+ allowBlank: false
+ })
+ }, {
+ header: "Password",
+ dataIndex: 'password',
+ renderer: function(value, metadata, record, row, col, store) {
+ setMetaAttr(metadata, record);
+ return '<span class="tvh-grid-unset">Hidden</span>';
+ },
+ editor: new fm.TextField({
+ allowBlank: false
+ })
+ }, {
+ header: "DES Key",
+ dataIndex: 'deskey',
+ width: 300,
+ renderer: function(value, metadata, record, row, col, store) {
+ setMetaAttr(metadata, record);
+ return '<span class="tvh-grid-unset">Hidden</span>';
+ },
+ editor: new fm.TextField({
+ allowBlank: false
+ })
+ }, {
+ xtype: 'checkcolumn',
+ header: "Update Card",
+ dataIndex: 'emm',
+ width: 100
+ }, {
+ xtype: 'checkcolumn',
+ header: "Update One",
+ dataIndex: 'emmex',
+ width: 100
+ }, {
+ header: "Comment",
+ dataIndex: 'comment',
+ width: 400,
+ renderer: function(value, metadata, record, row, col, store) {
+ setMetaAttr(metadata, record);
+ return value;
+ },
+ editor: new fm.TextField()
+ }]});
- var rec = Ext.data.Record.create([ 'enabled', 'connected', 'hostname',
- 'port', 'username', 'password', 'deskey', 'emm', 'emmex', 'comment' ]);
+ var rec = Ext.data.Record.create(['enabled', 'connected', 'hostname',
+ 'port', 'username', 'password', 'deskey', 'emm', 'emmex', 'comment']);
- var store = new Ext.data.JsonStore({
- root : 'entries',
- fields : rec,
- url : "tablemgr",
- autoLoad : true,
- id : 'id',
- baseParams : {
- table : 'cwc',
- op : "get"
- },
- sortInfo : {
- field : 'username',
- direction : 'ASC'
- }
- });
+ var store = new Ext.data.JsonStore({
+ root: 'entries',
+ fields: rec,
+ url: "tablemgr",
+ autoLoad: true,
+ id: 'id',
+ baseParams: {
+ table: 'cwc',
+ op: "get"
+ },
+ sortInfo: {
+ field: 'username',
+ direction: 'ASC'
+ }
+ });
- var grid = new tvheadend.tableEditor('Code Word Client', 'cwc', cm, rec, [],
- store, 'config_cwc.html', 'key');
+ var grid = new tvheadend.tableEditor('Code Word Client', 'cwc', cm, rec, [],
+ store, 'config_cwc.html', 'key');
- tvheadend.comet.on('cwcStatus', function(msg) {
- var rec = store.getById(msg.id);
- if (rec) {
- rec.set('connected', msg.connected);
- grid.getView().refresh();
- }
- });
+ tvheadend.comet.on('cwcStatus', function(msg) {
+ var rec = store.getById(msg.id);
+ if (rec) {
+ rec.set('connected', msg.connected);
+ grid.getView().refresh();
+ }
+ });
- return grid;
-}
+ return grid;
+};
tvheadend.weekdays = new Ext.data.SimpleStore({
- fields : [ 'identifier', 'name' ],
- id : 0,
- data : [ [ '1', 'Mon' ], [ '2', 'Tue' ], [ '3', 'Wed' ], [ '4', 'Thu' ],
- [ '5', 'Fri' ], [ '6', 'Sat' ], [ '7', 'Sun' ] ]
+ fields: ['identifier', 'name'],
+ id: 0,
+ data: [['1', 'Mon'], ['2', 'Tue'], ['3', 'Wed'], ['4', 'Thu'],
+ ['5', 'Fri'], ['6', 'Sat'], ['7', 'Sun']]
});
//This should be loaded from tvheadend
tvheadend.dvrprio = new Ext.data.SimpleStore({
- fields : [ 'identifier', 'name' ],
- id : 0,
- data : [ [ 'important', 'Important' ], [ 'high', 'High' ],
- [ 'normal', 'Normal' ], [ 'low', 'Low' ],
- [ 'unimportant', 'Unimportant' ] ]
+ fields: ['identifier', 'name'],
+ id: 0,
+ data: [['important', 'Important'], ['high', 'High'],
+ ['normal', 'Normal'], ['low', 'Low'],
+ ['unimportant', 'Unimportant']]
});
//For the container configuration
tvheadend.containers = new Ext.data.JsonStore({
- autoLoad : true,
- root : 'entries',
- fields : [ 'name', 'description' ],
- id : 'name',
- url : 'dvr_containers',
- baseParams : {
- op : 'list'
- }
+ autoLoad: true,
+ root: 'entries',
+ fields: ['name', 'description'],
+ id: 'name',
+ url: 'dvr_containers',
+ baseParams: {
+ op: 'list'
+ }
});
//For the cache configuration
tvheadend.caches = new Ext.data.JsonStore({
- autoLoad : true,
- root : 'entries',
- fields : [ 'index', 'description' ],
- id : 'name',
- url : 'dvr_caches',
- baseParams : {
- op : 'list'
- }
+ autoLoad: true,
+ root: 'entries',
+ fields: ['index', 'description'],
+ id: 'name',
+ url: 'dvr_caches',
+ baseParams: {
+ op: 'list'
+ }
});
* Configuration names
*/
tvheadend.configNames = new Ext.data.JsonStore({
- autoLoad : true,
- root : 'entries',
- fields : [ 'identifier', 'name' ],
- id : 'identifier',
- url : 'confignames',
- baseParams : {
- op : 'list'
- }
+ autoLoad: true,
+ root: 'entries',
+ fields: ['identifier', 'name'],
+ id: 'identifier',
+ url: 'confignames',
+ baseParams: {
+ op: 'list'
+ }
});
tvheadend.configNames.setDefaultSort('name', 'ASC');
tvheadend.comet.on('dvrconfig', function(m) {
- if (m.reload != null) tvheadend.configNames.reload();
+ if (m.reload != null)
+ tvheadend.configNames.reload();
});
/**
*/
tvheadend.dvrDetails = function(entry) {
- var content = '';
- var but;
-
- if (entry.chicon != null && entry.chicon.length > 0) content += '<img class="x-epg-chicon" src="'
- + entry.chicon + '">';
-
- content += '<div class="x-epg-title">' + entry.title + '</div>';
- content += '<div class="x-epg-desc">' + entry.description + '</div>';
- content += '<hr>'
- content += '<div class="x-epg-meta">Status: ' + entry.status + '</div>';
-
- if (entry.url != null && entry.filesize > 0) {
- content += '<div class="x-epg-meta">' + '<a href="' + entry.url
- + '" target="_blank">Download</a> '
- + parseInt(entry.filesize / 1000000) + ' MB</div>';
-
- }
-
- var win = new Ext.Window({
- title : entry.title,
- layout : 'fit',
- width : 400,
- height : 300,
- constrainHeader : true,
- buttonAlign : 'center',
- html : content
- });
-
- switch (entry.schedstate) {
- case 'scheduled':
- win.addButton({
- handler : cancelEvent,
- text : "Remove from schedule"
- });
- break;
-
- case 'recording':
- case 'recordingError':
- win.addButton({
- handler : cancelEvent,
- text : "Abort recording"
- });
- break;
- case 'completedError':
- case 'completed':
- win.addButton({
- handler : deleteEvent,
- text : "Delete recording"
- });
- break;
- }
-
- win.show();
-
- function cancelEvent() {
- Ext.Ajax.request({
- url : 'dvr',
- params : {
- entryId : entry.id,
- op : 'cancelEntry'
- },
-
- success : function(response, options) {
- win.close();
- },
-
- failure : function(response, options) {
- Ext.MessageBox.alert('DVR', response.statusText);
- }
- });
- }
-
- function deleteEvent() {
- Ext.Ajax.request({
- url : 'dvr',
- params : {
- entryId : entry.id,
- op : 'deleteEntry'
- },
-
- success : function(response, options) {
- win.close();
- },
-
- failure : function(response, options) {
- Ext.MessageBox.alert('DVR', response.statusText);
- }
- });
- }
-
-}
+ var content = '';
+ var but;
+
+ if (entry.chicon != null && entry.chicon.length > 0)
+ content += '<img class="x-epg-chicon" src="'
+ + entry.chicon + '">';
+
+ content += '<div class="x-epg-title">' + entry.title + '</div>';
+ content += '<div class="x-epg-desc">' + entry.description + '</div>';
+ content += '<hr>';
+ content += '<div class="x-epg-meta">Status: ' + entry.status + '</div>';
+
+ if (entry.url != null && entry.filesize > 0) {
+ content += '<div class="x-epg-meta">' + '<a href="' + entry.url
+ + '" target="_blank">Download</a> '
+ + parseInt(entry.filesize / 1000000) + ' MB</div>';
+
+ }
+
+ var win = new Ext.Window({
+ title: entry.title,
+ layout: 'fit',
+ width: 400,
+ height: 300,
+ constrainHeader: true,
+ buttonAlign: 'center',
+ html: content
+ });
+
+ switch (entry.schedstate) {
+ case 'scheduled':
+ win.addButton({
+ handler: cancelEvent,
+ text: "Remove from schedule"
+ });
+ break;
+
+ case 'recording':
+ case 'recordingError':
+ win.addButton({
+ handler: cancelEvent,
+ text: "Abort recording"
+ });
+ break;
+ case 'completedError':
+ case 'completed':
+ win.addButton({
+ handler: deleteEvent,
+ text: "Delete recording"
+ });
+ break;
+ }
+
+ win.show();
+
+ function cancelEvent() {
+ Ext.Ajax.request({
+ url: 'dvr',
+ params: {
+ entryId: entry.id,
+ op: 'cancelEntry'
+ },
+ success: function(response, options) {
+ win.close();
+ },
+ failure: function(response, options) {
+ Ext.MessageBox.alert('DVR', response.statusText);
+ }
+ });
+ }
+
+ function deleteEvent() {
+ Ext.Ajax.request({
+ url: 'dvr',
+ params: {
+ entryId: entry.id,
+ op: 'deleteEntry'
+ },
+ success: function(response, options) {
+ win.close();
+ },
+ failure: function(response, options) {
+ Ext.MessageBox.alert('DVR', response.statusText);
+ }
+ });
+ }
+
+};
/**
*
*/
tvheadend.dvrschedule = function(title, iconCls, dvrStore) {
- var actions = new Ext.ux.grid.RowActions({
- header : '',
- dataIndex : 'actions',
- width : 45,
- actions : [ {
- iconIndex : 'schedstate'
- } ]
- });
-
- function renderDate(value) {
- var dt = new Date(value);
- return dt.format('D j M H:i');
- }
-
- function renderDuration(value) {
- value = value / 60; /* Nevermind the seconds */
-
- if (value >= 60) {
- var min = parseInt(value % 60);
- var hours = parseInt(value / 60);
-
- if (min == 0) {
- return hours + ' hrs';
- }
- return hours + ' hrs, ' + min + ' min';
- }
- else {
- return parseInt(value) + ' min';
- }
- }
-
- function renderSize(value)
- {
- if (value == null)
- return '';
- return parseInt(value / 1000000) + ' MB';
- }
-
- function renderPri(value) {
- return tvheadend.dvrprio.getById(value).data.name;
- }
-
- var dvrCm = new Ext.grid.ColumnModel([ actions, {
- width : 250,
- id : 'title',
- header : "Title",
- dataIndex : 'title'
- }, {
- width : 100,
- id : 'episode',
- header : "Episode",
- dataIndex : 'episode'
- }, {
- width : 100,
- id : 'pri',
- header : "Priority",
- dataIndex : 'pri',
- renderer : renderPri,
- hidden : iconCls != 'clock',
- }, {
- width : 100,
- id : 'start',
- header : iconCls == 'clock' ? "Start" : "Date/Time",
- dataIndex : 'start',
- renderer : renderDate
- }, {
- width : 100,
- hidden : true,
- id : 'end',
- header : "End",
- dataIndex : 'end',
- renderer : renderDate
- }, {
- width : 100,
- id : 'duration',
- header : "Duration",
- dataIndex : 'duration',
- renderer : renderDuration
- }, {
- width : 100,
- id : 'filesize',
- header : "Filesize",
- dataIndex : 'filesize',
- renderer : renderSize,
- hidden : iconCls != 'television'
- }, {
- width : 250,
- id : 'channel',
- header : "Channel",
- dataIndex : 'channel'
- }, {
- width : 200,
- id : 'creator',
- header : "Created by",
- hidden : true,
- dataIndex : 'creator'
- }, {
- width : 200,
- id : 'config_name',
- header : "DVR Configuration",
- renderer : function(value, metadata, record, row, col, store) {
- if (!value) {
- return '<span class="tvh-grid-unset">(default)</span>';
- }
- else {
- return value;
- }
- },
- dataIndex : 'config_name',
- hidden: iconCls != 'clock'
- }, {
- width : 200,
- id : 'status',
- header : "Status",
- dataIndex : 'status',
- hidden: iconCls != 'exclamation'
- } ]);
-
- function addEntry() {
-
- function createRecording() {
- panel.getForm().submit({
- params : {
- 'op' : 'createEntry'
- },
- url : 'dvr/addentry',
- waitMsg : 'Creating entry...',
- failure : function(response, options) {
- Ext.MessageBox.alert('Server Error', 'Unable to create entry');
- },
- success : function() {
- win.close();
- }
- });
- }
-
- var panel = new Ext.FormPanel({
- frame : true,
- border : true,
- bodyStyle : 'padding:5px',
- labelAlign : 'right',
- labelWidth : 110,
- defaultType : 'textfield',
- items : [ new Ext.form.ComboBox({
- fieldLabel : 'Channel',
- name : 'channel',
- hiddenName : 'channelid',
- editable : false,
- allowBlank : false,
- displayField : 'val',
- valueField : 'key',
- mode : 'remote',
- triggerAction : 'all',
- store : tvheadend.channels
- }), new Ext.form.DateField({
- allowBlank : false,
- fieldLabel : 'Date',
- name : 'date'
- }), new Ext.form.TimeField({
- allowBlank : false,
- fieldLabel : 'Start time',
- name : 'starttime',
- increment : 10,
- format : 'H:i'
- }), new Ext.form.TimeField({
- allowBlank : false,
- fieldLabel : 'Stop time',
- name : 'stoptime',
- increment : 10,
- format : 'H:i'
- }), new Ext.form.ComboBox({
- store : tvheadend.dvrprio,
- value : "normal",
- triggerAction : 'all',
- mode : 'local',
- fieldLabel : 'Priority',
- valueField : 'identifier',
- displayField : 'name',
- name : 'pri'
- }), {
- allowBlank : false,
- fieldLabel : 'Title',
- name : 'title'
- }, new Ext.form.ComboBox({
- store : tvheadend.configNames,
- triggerAction : 'all',
- mode : 'local',
- fieldLabel : 'DVR Configuration',
- valueField : 'identifier',
- displayField : 'name',
- name : 'config_name',
- emptyText : '(default)',
- value : '',
- editable : false
- }) ],
- buttons : [ {
- text : 'Create',
- handler : createRecording
- } ]
-
- });
-
- win = new Ext.Window({
- title : 'Add single recording',
- layout : 'fit',
- width : 500,
- height : 300,
- plain : true,
- items : panel
- });
- win.show();
- new Ext.form.ComboBox({
- store : tvheadend.configNames,
- triggerAction : 'all',
- mode : 'local',
- fieldLabel : 'DVR Configuration',
- valueField : 'identifier',
- displayField : 'name',
- name : 'config_name',
- emptyText : '(default)',
- value : '',
- editable : false
- })
- }
- ;
-
- var panel = new Ext.grid.GridPanel({
- loadMask : true,
- stripeRows : true,
- disableSelection : true,
- title : title,
- iconCls : iconCls,
- store : dvrStore,
- cm : dvrCm,
- plugins : [ actions ],
- viewConfig : {
- forceFit : true
- },
- tbar : [ {
- tooltip : 'Schedule a new recording session on the server.',
- iconCls : 'add',
- text : 'Add entry',
- handler : addEntry
- }, '->', {
- text : 'Help',
- handler : function() {
- new tvheadend.help('Digital Video Recorder', 'dvrlog.html');
- }
- } ],
- bbar : new Ext.PagingToolbar({
- store : dvrStore,
- pageSize : 20,
- displayInfo : true,
- displayMsg : 'Programs {0} - {1} of {2}',
- emptyMsg : "No programs to display"
- })
-
- });
-
- panel.on('rowclick', rowclicked);
- function rowclicked(grid, index) {
- new tvheadend.dvrDetails(grid.getStore().getAt(index).data);
- }
- return panel;
-}
+ var actions = new Ext.ux.grid.RowActions({
+ header: '',
+ dataIndex: 'actions',
+ width: 45,
+ actions: [{
+ iconIndex: 'schedstate'
+ }]
+ });
+
+ function renderDate(value) {
+ var dt = new Date(value);
+ return dt.format('D j M H:i');
+ }
+
+ function renderDuration(value) {
+ value = value / 60; /* Nevermind the seconds */
+
+ if (value >= 60) {
+ var min = parseInt(value % 60);
+ var hours = parseInt(value / 60);
+
+ if (min === 0) {
+ return hours + ' hrs';
+ }
+ return hours + ' hrs, ' + min + ' min';
+ }
+ else {
+ return parseInt(value) + ' min';
+ }
+ }
+
+ function renderSize(value)
+ {
+ if (value == null)
+ return '';
+ return parseInt(value / 1000000) + ' MB';
+ }
+
+ function renderPri(value) {
+ return tvheadend.dvrprio.getById(value).data.name;
+ }
+
+ var dvrCm = new Ext.grid.ColumnModel([actions, {
+ width: 250,
+ id: 'title',
+ header: "Title",
+ dataIndex: 'title'
+ }, {
+ width: 100,
+ id: 'episode',
+ header: "Episode",
+ dataIndex: 'episode'
+ }, {
+ width: 100,
+ id: 'pri',
+ header: "Priority",
+ dataIndex: 'pri',
+ renderer: renderPri,
+ hidden: iconCls !== 'clock'
+ }, {
+ width: 100,
+ id: 'start',
+ header: iconCls === 'clock' ? "Start" : "Date/Time",
+ dataIndex: 'start',
+ renderer: renderDate
+ }, {
+ width: 100,
+ hidden: true,
+ id: 'end',
+ header: "End",
+ dataIndex: 'end',
+ renderer: renderDate
+ }, {
+ width: 100,
+ id: 'duration',
+ header: "Duration",
+ dataIndex: 'duration',
+ renderer: renderDuration
+ }, {
+ width: 100,
+ id: 'filesize',
+ header: "Filesize",
+ dataIndex: 'filesize',
+ renderer: renderSize,
+ hidden: iconCls !== 'television'
+ }, {
+ width: 250,
+ id: 'channel',
+ header: "Channel",
+ dataIndex: 'channel'
+ }, {
+ width: 200,
+ id: 'creator',
+ header: "Created by",
+ hidden: true,
+ dataIndex: 'creator'
+ }, {
+ width: 200,
+ id: 'config_name',
+ header: "DVR Configuration",
+ renderer: function(value, metadata, record, row, col, store) {
+ if (!value) {
+ return '<span class="tvh-grid-unset">(default)</span>';
+ }
+ else {
+ return value;
+ }
+ },
+ dataIndex: 'config_name',
+ hidden: iconCls !== 'clock'
+ }, {
+ width: 200,
+ id: 'status',
+ header: "Status",
+ dataIndex: 'status',
+ hidden: iconCls !== 'exclamation'
+ }]);
+
+ function addEntry() {
+
+ function createRecording() {
+ panel.getForm().submit({
+ params: {
+ 'op': 'createEntry'
+ },
+ url: 'dvr/addentry',
+ waitMsg: 'Creating entry...',
+ failure: function(response, options) {
+ Ext.MessageBox.alert('Server Error', 'Unable to create entry');
+ },
+ success: function() {
+ win.close();
+ }
+ });
+ }
+
+ var panel = new Ext.FormPanel({
+ frame: true,
+ border: true,
+ bodyStyle: 'padding:5px',
+ labelAlign: 'right',
+ labelWidth: 110,
+ defaultType: 'textfield',
+ items: [new Ext.form.ComboBox({
+ fieldLabel: 'Channel',
+ name: 'channel',
+ hiddenName: 'channelid',
+ editable: false,
+ allowBlank: false,
+ displayField: 'val',
+ valueField: 'key',
+ mode: 'remote',
+ triggerAction: 'all',
+ store: tvheadend.channels
+ }), new Ext.form.DateField({
+ allowBlank: false,
+ fieldLabel: 'Date',
+ name: 'date'
+ }), new Ext.form.TimeField({
+ allowBlank: false,
+ fieldLabel: 'Start time',
+ name: 'starttime',
+ increment: 10,
+ format: 'H:i'
+ }), new Ext.form.TimeField({
+ allowBlank: false,
+ fieldLabel: 'Stop time',
+ name: 'stoptime',
+ increment: 10,
+ format: 'H:i'
+ }), new Ext.form.ComboBox({
+ store: tvheadend.dvrprio,
+ value: "normal",
+ triggerAction: 'all',
+ mode: 'local',
+ fieldLabel: 'Priority',
+ valueField: 'identifier',
+ displayField: 'name',
+ name: 'pri'
+ }), {
+ allowBlank: false,
+ fieldLabel: 'Title',
+ name: 'title'
+ }, new Ext.form.ComboBox({
+ store: tvheadend.configNames,
+ triggerAction: 'all',
+ mode: 'local',
+ fieldLabel: 'DVR Configuration',
+ valueField: 'identifier',
+ displayField: 'name',
+ name: 'config_name',
+ emptyText: '(default)',
+ value: '',
+ editable: false
+ })],
+ buttons: [{
+ text: 'Create',
+ handler: createRecording
+ }]
+
+ });
+
+ win = new Ext.Window({
+ title: 'Add single recording',
+ layout: 'fit',
+ width: 500,
+ height: 300,
+ plain: true,
+ items: panel
+ });
+ win.show();
+ new Ext.form.ComboBox({
+ store: tvheadend.configNames,
+ triggerAction: 'all',
+ mode: 'local',
+ fieldLabel: 'DVR Configuration',
+ valueField: 'identifier',
+ displayField: 'name',
+ name: 'config_name',
+ emptyText: '(default)',
+ value: '',
+ editable: false
+ });
+ }
+ ;
+
+ var panel = new Ext.grid.GridPanel({
+ loadMask: true,
+ stripeRows: true,
+ disableSelection: true,
+ title: title,
+ iconCls: iconCls,
+ store: dvrStore,
+ cm: dvrCm,
+ plugins: [actions],
+ viewConfig: {
+ forceFit: true
+ },
+ tbar: [{
+ tooltip: 'Schedule a new recording session on the server.',
+ iconCls: 'add',
+ text: 'Add entry',
+ handler: addEntry
+ }, '->', {
+ text: 'Help',
+ handler: function() {
+ new tvheadend.help('Digital Video Recorder', 'dvrlog.html');
+ }
+ }],
+ bbar: new Ext.PagingToolbar({
+ store: dvrStore,
+ pageSize: 20,
+ displayInfo: true,
+ displayMsg: 'Programs {0} - {1} of {2}',
+ emptyMsg: "No programs to display"
+ })
+
+ });
+
+ panel.on('rowclick', rowclicked);
+ function rowclicked(grid, index) {
+ new tvheadend.dvrDetails(grid.getStore().getAt(index).data);
+ }
+ return panel;
+};
/**
*
*
*/
tvheadend.autoreceditor = function() {
- var fm = Ext.form;
-
-
- var cm = new Ext.grid.ColumnModel({
- defaultSortable: true,
- columns :
- [
- {
- header: 'Enabled',
- dataIndex: 'enabled',
- width: 30,
- xtype: 'checkcolumn'
- },
-
- {
- header : "Title (Regexp)",
- dataIndex : 'title',
- editor : new fm.TextField({
- allowBlank : true
- })
- },
- {
- header : "Channel",
- dataIndex : 'channel',
- editor : new Ext.form.ComboBox({
- loadingText : 'Loading...',
- displayField : 'val',
- valueField: 'key',
- store : tvheadend.channels,
- mode : 'local',
- editable : false,
- triggerAction : 'all',
- emptyText : 'Only include channel...'
- }),
- renderer : function (v, m, r) {
- var i = tvheadend.channels.find('key', v);
- if (i != -1)
- v = tvheadend.channels.getAt(i).get('val')
- return v
- }
- },
- {
- header : "SeriesLink",
- dataIndex : 'serieslink',
- renderer : function(v) {
- return v ? 'yes' : 'no';
- }
- },
- {
- header : "Channel tag",
- dataIndex : 'tag',
- editor : new Ext.form.ComboBox({
- displayField : 'name',
- store : tvheadend.channelTags,
- mode : 'local',
- editable : false,
- triggerAction : 'all',
- emptyText : 'Only include tag...'
- })
- },
- {
- header : "Genre",
- dataIndex : 'contenttype',
- renderer : function(v) {
- return tvheadend.contentGroupLookupName(v);
- },
- editor : new Ext.form.ComboBox({
- valueField : 'code',
- displayField : 'name',
- store : tvheadend.ContentGroupStore,
- mode : 'local',
- editable : false,
- triggerAction : 'all',
- emptyText : 'Only include content...'
- })
- },
- {
- header : "Weekdays",
- dataIndex : 'weekdays',
- renderer : function(value, metadata, record, row, col, store) {
- if (value.split) value = value.split(',')
- if (value.length == 7) return 'All days';
- if (value.length == 0 || value[0] == "") return 'No days';
- ret = [];
- tags = value;
- for ( var i = 0; i < tags.length; i++) {
- var tag = tvheadend.weekdays.getById(tags[i]);
- if (typeof tag !== 'undefined') ret.push(tag.data.name);
- }
- return ret.join(', ');
- },
- editor : new Ext.ux.form.LovCombo({
- store : tvheadend.weekdays,
- mode : 'local',
- valueField : 'identifier',
- displayField : 'name'
- })
- }, {
- header : "Starting Around",
- dataIndex : 'approx_time',
- renderer : function(value, metadata, record, row, col, store) {
- if (typeof value === 'string') return value;
-
- if (value === 0) return '';
-
- var hours = Math.floor(value / 60);
- var mins = value % 60;
- var dt = new Date();
- dt.setHours(hours);
- dt.setMinutes(mins);
- return dt.format('H:i');
- },
- editor : new Ext.form.TimeField({
- allowBlank : true,
- increment : 10,
- format : 'H:i'
- })
- }, {
- header : "Priority",
- dataIndex : 'pri',
- width : 100,
- renderer : function(value, metadata, record, row, col, store) {
- return tvheadend.dvrprio.getById(value).data.name;
- },
- editor : new fm.ComboBox({
- store : tvheadend.dvrprio,
- triggerAction : 'all',
- mode : 'local',
- valueField : 'identifier',
- displayField : 'name'
- })
- }, {
- header : "DVR Configuration",
- dataIndex : 'config_name',
- renderer : function(value, metadata, record, row, col, store) {
- if (!value) {
- return '<span class="tvh-grid-unset">(default)</span>';
- }
- else {
- return value;
- }
- },
- editor : new Ext.form.ComboBox({
- store : tvheadend.configNames,
- triggerAction : 'all',
- mode : 'local',
- valueField : 'identifier',
- displayField : 'name',
- name : 'config_name',
- emptyText : '(default)',
- editable : false
- })
- }, {
- header : "Created by",
- dataIndex : 'creator',
- editor : new fm.TextField({
- allowBlank : false
- })
- }, {
- header : "Comment",
- dataIndex : 'comment',
- editor : new fm.TextField({
- allowBlank : false
- })
- } ]});
-
- return new tvheadend.tableEditor('Automatic Recorder', 'autorec', cm,
- tvheadend.autorecRecord, [], tvheadend.autorecStore,
- 'autorec.html', 'wand');
-}
+ var fm = Ext.form;
+
+
+ var cm = new Ext.grid.ColumnModel({
+ defaultSortable: true,
+ columns:
+ [
+ {
+ header: 'Enabled',
+ dataIndex: 'enabled',
+ width: 30,
+ xtype: 'checkcolumn'
+ },
+ {
+ header: "Title (Regexp)",
+ dataIndex: 'title',
+ editor: new fm.TextField({
+ allowBlank: true
+ })
+ },
+ {
+ header: "Channel",
+ dataIndex: 'channel',
+ editor: new Ext.form.ComboBox({
+ loadingText: 'Loading...',
+ displayField: 'val',
+ valueField: 'key',
+ store: tvheadend.channels,
+ mode: 'local',
+ editable: false,
+ triggerAction: 'all',
+ emptyText: 'Only include channel...'
+ }),
+ renderer: function(v, m, r) {
+ var i = tvheadend.channels.find('key', v);
+ if (i !== -1)
+ v = tvheadend.channels.getAt(i).get('val');
+ return v;
+ }
+ },
+ {
+ header: "SeriesLink",
+ dataIndex: 'serieslink',
+ renderer: function(v) {
+ return v ? 'yes' : 'no';
+ }
+ },
+ {
+ header: "Channel tag",
+ dataIndex: 'tag',
+ editor: new Ext.form.ComboBox({
+ displayField: 'name',
+ store: tvheadend.channelTags,
+ mode: 'local',
+ editable: false,
+ triggerAction: 'all',
+ emptyText: 'Only include tag...'
+ })
+ },
+ {
+ header: "Genre",
+ dataIndex: 'contenttype',
+ renderer: function(v) {
+ return tvheadend.contentGroupLookupName(v);
+ },
+ editor: new Ext.form.ComboBox({
+ valueField: 'code',
+ displayField: 'name',
+ store: tvheadend.ContentGroupStore,
+ mode: 'local',
+ editable: false,
+ triggerAction: 'all',
+ emptyText: 'Only include content...'
+ })
+ },
+ {
+ header: "Weekdays",
+ dataIndex: 'weekdays',
+ renderer: function(value, metadata, record, row, col, store) {
+ if (value.split)
+ value = value.split(',');
+ if (value.length === 7)
+ return 'All days';
+ if (value.length === 0 || value[0] === "")
+ return 'No days';
+ ret = [];
+ tags = value;
+ for (var i = 0; i < tags.length; i++) {
+ var tag = tvheadend.weekdays.getById(tags[i]);
+ if (typeof tag !== 'undefined')
+ ret.push(tag.data.name);
+ }
+ return ret.join(', ');
+ },
+ editor: new Ext.ux.form.LovCombo({
+ store: tvheadend.weekdays,
+ mode: 'local',
+ valueField: 'identifier',
+ displayField: 'name'
+ })
+ }, {
+ header: "Starting Around",
+ dataIndex: 'approx_time',
+ renderer: function(value, metadata, record, row, col, store) {
+ if (typeof value === 'string')
+ return value;
+
+ if (value === 0)
+ return '';
+
+ var hours = Math.floor(value / 60);
+ var mins = value % 60;
+ var dt = new Date();
+ dt.setHours(hours);
+ dt.setMinutes(mins);
+ return dt.format('H:i');
+ },
+ editor: new Ext.form.TimeField({
+ allowBlank: true,
+ increment: 10,
+ format: 'H:i'
+ })
+ }, {
+ header: "Priority",
+ dataIndex: 'pri',
+ width: 100,
+ renderer: function(value, metadata, record, row, col, store) {
+ return tvheadend.dvrprio.getById(value).data.name;
+ },
+ editor: new fm.ComboBox({
+ store: tvheadend.dvrprio,
+ triggerAction: 'all',
+ mode: 'local',
+ valueField: 'identifier',
+ displayField: 'name'
+ })
+ }, {
+ header: "DVR Configuration",
+ dataIndex: 'config_name',
+ renderer: function(value, metadata, record, row, col, store) {
+ if (!value) {
+ return '<span class="tvh-grid-unset">(default)</span>';
+ }
+ else {
+ return value;
+ }
+ },
+ editor: new Ext.form.ComboBox({
+ store: tvheadend.configNames,
+ triggerAction: 'all',
+ mode: 'local',
+ valueField: 'identifier',
+ displayField: 'name',
+ name: 'config_name',
+ emptyText: '(default)',
+ editable: false
+ })
+ }, {
+ header: "Created by",
+ dataIndex: 'creator',
+ editor: new fm.TextField({
+ allowBlank: false
+ })
+ }, {
+ header: "Comment",
+ dataIndex: 'comment',
+ editor: new fm.TextField({
+ allowBlank: false
+ })
+ }]});
+
+ return new tvheadend.tableEditor('Automatic Recorder', 'autorec', cm,
+ tvheadend.autorecRecord, [], tvheadend.autorecStore,
+ 'autorec.html', 'wand');
+};
/**
*
*/
tvheadend.dvr = function() {
- function datastoreBuilder(url) {
- return new Ext.data.JsonStore({
- root : 'entries',
- totalProperty : 'totalCount',
- fields : [ {
- name : 'id'
- }, {
- name : 'channel'
- }, {
- name : 'title'
- }, {
- name : 'episode'
- }, {
- name : 'pri'
- }, {
- name : 'description'
- }, {
- name : 'chicon'
- }, {
- name : 'start',
- type : 'date',
- dateFormat : 'U' /* unix time */
- }, {
- name : 'end',
- type : 'date',
- dateFormat : 'U' /* unix time */
- }, {
- name : 'config_name'
- }, {
- name : 'status'
- }, {
- name : 'schedstate'
- }, {
- name : 'error'
- }, {
- name : 'creator'
- }, {
- name : 'duration'
- }, {
- name : 'filesize'
- }, {
- name : 'url'
- } ],
- url : url,
- autoLoad : true,
- id : 'id',
- remoteSort : true
- });
- }
- tvheadend.dvrStoreUpcoming = datastoreBuilder('dvrlist_upcoming');
- tvheadend.dvrStoreFinished = datastoreBuilder('dvrlist_finished');
- tvheadend.dvrStoreFailed = datastoreBuilder('dvrlist_failed');
- tvheadend.dvrStores = [tvheadend.dvrStoreUpcoming,
- tvheadend.dvrStoreFinished,
- tvheadend.dvrStoreFailed];
-
-
- function updateDvrStore(store, r, m) {
- r.data.status = m.status;
- r.data.schedstate = m.schedstate;
-
- store.afterEdit(r);
- store.fireEvent('updated', store, r,
- Ext.data.Record.COMMIT);
- }
-
- function reloadStores() {
- for (var i = 0; i < tvheadend.dvrStores.length; i++) {
- tvheadend.dvrStores[i].reload();
- }
- }
-
- tvheadend.comet.on('dvrdb', function(m) {
-
- if (m.reload != null) {
- reloadStores();
- }
-
- if (m.updateEntry != null) {
- for (var i = 0; i < tvheadend.dvrStores.length; i++) {
- var store = tvheadend.dvrStores[i];
- r = tvheadend.dvrStoreUpcoming.getById(m.id);
- if (typeof r !== 'undefined') {
- updateDvrStore(store, r, m);
- return;
- }
- }
- reloadStores();
- }
- });
-
- tvheadend.autorecRecord = Ext.data.Record.create([ 'enabled', 'title',
- 'serieslink', 'channel', 'tag', 'creator', 'contenttype', 'comment',
- 'weekdays', 'pri', 'approx_time', 'config_name' ]);
-
- tvheadend.autorecStore = new Ext.data.JsonStore({
- root : 'entries',
- fields : tvheadend.autorecRecord,
- url : "tablemgr",
- autoLoad : true,
- id : 'id',
- baseParams : {
- table : "autorec",
- op : "get"
- }
- });
-
- tvheadend.comet.on('autorec', function(m) {
- if (m.reload != null) tvheadend.autorecStore.reload();
- });
-
- var panel = new Ext.TabPanel({
- activeTab : 0,
- autoScroll : true,
- title : 'Digital Video Recorder',
- iconCls : 'drive',
- items : [
- new tvheadend.dvrschedule('Upcoming recordings', 'clock', tvheadend.dvrStoreUpcoming),
- new tvheadend.dvrschedule('Finished recordings', 'television', tvheadend.dvrStoreFinished),
- new tvheadend.dvrschedule('Failed recordings', 'exclamation', tvheadend.dvrStoreFailed),
- new tvheadend.autoreceditor
- ]
- });
- return panel;
-}
+ function datastoreBuilder(url) {
+ return new Ext.data.JsonStore({
+ root: 'entries',
+ totalProperty: 'totalCount',
+ fields: [{
+ name: 'id'
+ }, {
+ name: 'channel'
+ }, {
+ name: 'title'
+ }, {
+ name: 'episode'
+ }, {
+ name: 'pri'
+ }, {
+ name: 'description'
+ }, {
+ name: 'chicon'
+ }, {
+ name: 'start',
+ type: 'date',
+ dateFormat: 'U' /* unix time */
+ }, {
+ name: 'end',
+ type: 'date',
+ dateFormat: 'U' /* unix time */
+ }, {
+ name: 'config_name'
+ }, {
+ name: 'status'
+ }, {
+ name: 'schedstate'
+ }, {
+ name: 'error'
+ }, {
+ name: 'creator'
+ }, {
+ name: 'duration'
+ }, {
+ name: 'filesize'
+ }, {
+ name: 'url'
+ }],
+ url: url,
+ autoLoad: true,
+ id: 'id',
+ remoteSort: true
+ });
+ }
+ tvheadend.dvrStoreUpcoming = datastoreBuilder('dvrlist_upcoming');
+ tvheadend.dvrStoreFinished = datastoreBuilder('dvrlist_finished');
+ tvheadend.dvrStoreFailed = datastoreBuilder('dvrlist_failed');
+ tvheadend.dvrStores = [tvheadend.dvrStoreUpcoming,
+ tvheadend.dvrStoreFinished,
+ tvheadend.dvrStoreFailed];
+
+
+ function updateDvrStore(store, r, m) {
+ r.data.status = m.status;
+ r.data.schedstate = m.schedstate;
+
+ store.afterEdit(r);
+ store.fireEvent('updated', store, r,
+ Ext.data.Record.COMMIT);
+ }
+
+ function reloadStores() {
+ for (var i = 0; i < tvheadend.dvrStores.length; i++) {
+ tvheadend.dvrStores[i].reload();
+ }
+ }
+
+ tvheadend.comet.on('dvrdb', function(m) {
+
+ if (m.reload != null) {
+ reloadStores();
+ }
+
+ if (m.updateEntry != null) {
+ for (var i = 0; i < tvheadend.dvrStores.length; i++) {
+ var store = tvheadend.dvrStores[i];
+ r = tvheadend.dvrStoreUpcoming.getById(m.id);
+ if (typeof r !== 'undefined') {
+ updateDvrStore(store, r, m);
+ return;
+ }
+ }
+ reloadStores();
+ }
+ });
+
+ tvheadend.autorecRecord = Ext.data.Record.create(['enabled', 'title',
+ 'serieslink', 'channel', 'tag', 'creator', 'contenttype', 'comment',
+ 'weekdays', 'pri', 'approx_time', 'config_name']);
+
+ tvheadend.autorecStore = new Ext.data.JsonStore({
+ root: 'entries',
+ fields: tvheadend.autorecRecord,
+ url: "tablemgr",
+ autoLoad: true,
+ id: 'id',
+ baseParams: {
+ table: "autorec",
+ op: "get"
+ }
+ });
+
+ tvheadend.comet.on('autorec', function(m) {
+ if (m.reload != null)
+ tvheadend.autorecStore.reload();
+ });
+
+ var panel = new Ext.TabPanel({
+ activeTab: 0,
+ autoScroll: true,
+ title: 'Digital Video Recorder',
+ iconCls: 'drive',
+ items: [
+ new tvheadend.dvrschedule('Upcoming recordings', 'clock', tvheadend.dvrStoreUpcoming),
+ new tvheadend.dvrschedule('Finished recordings', 'television', tvheadend.dvrStoreFinished),
+ new tvheadend.dvrschedule('Failed recordings', 'exclamation', tvheadend.dvrStoreFailed),
+ new tvheadend.autoreceditor
+ ]
+ });
+ return panel;
+};
/**
* Configuration panel (located under configuration)
*/
tvheadend.dvrsettings = function() {
- var confreader = new Ext.data.JsonReader({
- root : 'dvrSettings'
- }, [ 'storage', 'filePermissions', 'dirPermissions', 'postproc', 'retention', 'dayDirs', 'channelDirs',
- 'channelInTitle', 'container', 'cache', 'dateInTitle', 'timeInTitle',
- 'preExtraTime', 'postExtraTime', 'whitespaceInTitle', 'titleDirs',
- 'episodeInTitle', 'cleanTitle', 'tagFiles', 'commSkip', 'subtitleInTitle',
- 'episodeBeforeDate', 'rewritePAT', 'rewritePMT' ]);
-
- var confcombo = new Ext.form.ComboBox({
- store : tvheadend.configNames,
- triggerAction : 'all',
- mode : 'local',
- displayField : 'name',
- name : 'config_name',
- emptyText : '(default)',
- value : '',
- editable : true
- });
-
- var delButton = new Ext.Toolbar.Button({
- tooltip : 'Delete named configuration',
- iconCls : 'remove',
- text : "Delete configuration",
- handler : deleteConfiguration,
- disabled : true
- });
-
-/* Config panel variables */
-
-/* DVR Behaviour */
-
- var recordingContainer = new Ext.form.ComboBox({
- store : tvheadend.containers,
- fieldLabel : 'Media container',
- triggerAction : 'all',
- displayField : 'description',
- valueField : 'name',
- editable : false,
- width : 200,
- hiddenName : 'container'
- });
-
- var cacheScheme = new Ext.form.ComboBox({
- store : tvheadend.caches,
- fieldLabel : 'Cache scheme',
- triggerAction : 'all',
- displayField : 'description',
- valueField : 'index',
- editable : false,
- width : 200,
- hiddenName : 'cache'
- });
-
- var logRetention = new Ext.form.NumberField({
- allowNegative : false,
- allowDecimals : false,
- minValue : 1,
- fieldLabel : 'DVR Log retention time (days)',
- name : 'retention'
- });
-
- var timeBefore = new Ext.form.NumberField({
- allowDecimals : false,
- fieldLabel : 'Extra time before recordings (minutes)',
- name : 'preExtraTime'
+ var confreader = new Ext.data.JsonReader({
+ root: 'dvrSettings'
+ }, ['storage', 'filePermissions', 'dirPermissions', 'postproc', 'retention', 'dayDirs', 'channelDirs',
+ 'channelInTitle', 'container', 'cache', 'dateInTitle', 'timeInTitle',
+ 'preExtraTime', 'postExtraTime', 'whitespaceInTitle', 'titleDirs',
+ 'episodeInTitle', 'cleanTitle', 'tagFiles', 'commSkip', 'subtitleInTitle',
+ 'episodeBeforeDate', 'rewritePAT', 'rewritePMT']);
+
+ var confcombo = new Ext.form.ComboBox({
+ store: tvheadend.configNames,
+ triggerAction: 'all',
+ mode: 'local',
+ displayField: 'name',
+ name: 'config_name',
+ emptyText: '(default)',
+ value: '',
+ editable: true
+ });
+
+ var delButton = new Ext.Toolbar.Button({
+ tooltip: 'Delete named configuration',
+ iconCls: 'remove',
+ text: "Delete configuration",
+ handler: deleteConfiguration,
+ disabled: true
+ });
+
+ /* Config panel variables */
+
+ /* DVR Behaviour */
+
+ var recordingContainer = new Ext.form.ComboBox({
+ store: tvheadend.containers,
+ fieldLabel: 'Media container',
+ triggerAction: 'all',
+ displayField: 'description',
+ valueField: 'name',
+ editable: false,
+ width: 200,
+ hiddenName: 'container'
+ });
+
+ var cacheScheme = new Ext.form.ComboBox({
+ store: tvheadend.caches,
+ fieldLabel: 'Cache scheme',
+ triggerAction: 'all',
+ displayField: 'description',
+ valueField: 'index',
+ editable: false,
+ width: 200,
+ hiddenName: 'cache'
+ });
+
+ var logRetention = new Ext.form.NumberField({
+ allowNegative: false,
+ allowDecimals: false,
+ minValue: 1,
+ fieldLabel: 'DVR Log retention time (days)',
+ name: 'retention'
+ });
+
+ var timeBefore = new Ext.form.NumberField({
+ allowDecimals: false,
+ fieldLabel: 'Extra time before recordings (minutes)',
+ name: 'preExtraTime'
});
-
+
var timeAfter = new Ext.form.NumberField({
- allowDecimals : false,
- fieldLabel : 'Extra time after recordings (minutes)',
- name : 'postExtraTime'
- });
-
- var postProcessing = new Ext.form.TextField({
- width : 300,
- fieldLabel : 'Post-processor command',
- name : 'postproc'
- });
-
-/* Recording File Options */
-
- var recordingPath = new Ext.form.TextField({
- width : 300,
- fieldLabel : 'Recording system path',
- name : 'storage'
- });
-
-/* NB: recordingPermissions is defined as a TextField for validation purposes (leading zeros), but is ultimately a number */
-
- var recordingPermissions = new Ext.form.TextField({
- regex : /^[0][0-7]{3}$/,
- maskRe : /[0-7]/,
- width : 100,
- allowBlank : false,
- blankText : 'You must provide a value - use octal chmod notation, e.g. 0664',
- fieldLabel : 'File permissions (octal, e.g. 0664)',
- name : 'filePermissions'
- });
-
-/* TO DO - Add 'override user umask?' option, then trigger fchmod in mkmux.c, muxer_pass.c after file created */
-
- var PATrewrite = new Ext.form.Checkbox({
- fieldLabel : 'Rewrite PAT in passthrough mode',
- name : 'rewritePAT'
- });
-
- var PMTrewrite = new Ext.form.Checkbox({
- fieldLabel : 'Rewrite PMT in passthrough mode',
- name : 'rewritePMT'
- });
-
- var tagMetadata = new Ext.form.Checkbox({
- fieldLabel : 'Tag files with metadata',
- name : 'tagFiles'
- });
-
- var skipCommercials = new Ext.form.Checkbox({
- fieldLabel : 'Skip commercials',
- name : 'commSkip'
- });
-
-/* Subdirectories and filename handling */
-
-/* NB: directoryPermissions is defined as a TextField for validation purposes (leading zeros), but is ultimately a number */
-
- var directoryPermissions = new Ext.form.TextField({
- regex : /^[0][0-7]{3}$/,
- maskRe : /[0-7]/,
- width : 100,
- allowBlank : false,
- blankText : 'You must provide a value - use octal chmod notation, e.g. 0775',
- fieldLabel : 'Directory permissions (octal, e.g. 0775)',
- name : 'dirPermissions'
- });
-
-/* TO DO - Add 'override user umask?' option, then trigger fchmod in utils.c after directory created */
-
- var dirsPerDay = new Ext.form.Checkbox({
- fieldLabel : 'Make subdirectories per day',
- name : 'dayDirs'
- });
-
- var dirsPerChannel = new Ext.form.Checkbox({
- fieldLabel : 'Make subdirectories per channel',
- name : 'channelDirs'
- });
-
- var dirsPerTitle = new Ext.form.Checkbox({
- fieldLabel : 'Make subdirectories per title',
- name : 'titleDirs'
- });
-
- var incChannelInTitle = new Ext.form.Checkbox({
- fieldLabel : 'Include channel name in filename',
- name : 'channelInTitle'
- });
-
- var incDateInTitle = new Ext.form.Checkbox({
- fieldLabel : 'Include date in filename',
- name : 'dateInTitle'
- });
-
- var incTimeInTitle = new Ext.form.Checkbox({
- fieldLabel : 'Include time in filename',
- name : 'timeInTitle'
- });
-
- var incEpisodeInTitle = new Ext.form.Checkbox({
- fieldLabel : 'Include episode in filename',
- name : 'episodeInTitle'
- });
-
- var incSubtitleInTitle = new Ext.form.Checkbox({
- fieldLabel : 'Include subtitle in filename',
- name : 'subtitleInTitle'
- });
-
- var episodeFirst = new Ext.form.Checkbox({
- fieldLabel : 'Put episode in filename before date and time',
- name : 'episodeBeforeDate'
- });
-
- var stripUnsafeChars = new Ext.form.Checkbox({
- fieldLabel : 'Remove all unsafe characters from filename',
- name : 'cleanTitle'
- });
-
- var stripWhitespace = new Ext.form.Checkbox({
- fieldLabel : 'Replace whitespace in title with \'-\'',
- name : 'whitespaceInTitle'
- });
-
-
-/* Sub-Panel - DVR behaviour */
-
- var DVRBehaviour = new Ext.form.FieldSet({
- title: 'DVR Behaviour',
- width: 700,
- autoHeight: true,
- collapsible: true,
- items : [ recordingContainer, cacheScheme, logRetention, timeBefore, timeAfter, postProcessing ]
- });
-
-/* Sub-Panel - File Output */
-
- var FileOutputPanel = new Ext.form.FieldSet({
- title: 'Recording File Options',
- width: 700,
- autoHeight: true,
- collapsible: true,
- items : [ recordingPath, recordingPermissions, PATrewrite, PMTrewrite, tagMetadata, skipCommercials ]
- });
-
-/* Sub-Panel - Directory operations */
-
- var DirHandlingPanel = new Ext.form.FieldSet({
- title: 'Subdirectory Options',
- width: 700,
- autoHeight: true,
- collapsible: true,
- items : [ directoryPermissions, dirsPerDay, dirsPerChannel, dirsPerTitle ]
- });
-
-/* Sub-Panel - File operations */
-
- var FileHandlingPanel = new Ext.form.FieldSet({
- title: 'Filename Options',
- width: 700,
- autoHeight: true,
- collapsible: true,
- items : [ incChannelInTitle, incDateInTitle, incTimeInTitle, incEpisodeInTitle,
- incSubtitleInTitle, episodeFirst, stripUnsafeChars, stripWhitespace ]
- });
-
-/* Main (form) panel */
-
- var confpanel = new Ext.FormPanel({
- title : 'Digital Video Recorder',
- iconCls : 'drive',
- border : false,
- bodyStyle : 'padding:15px',
- anchor : '100% 50%',
- labelAlign : 'right',
- labelWidth : 250,
- waitMsgTarget : true,
- reader : confreader,
- defaultType : 'textfield',
- layout : 'form',
- items : [ DVRBehaviour, FileOutputPanel, DirHandlingPanel, FileHandlingPanel ],
-
- tbar : [ confcombo, {
- tooltip : 'Save changes made to dvr configuration below',
- iconCls : 'save',
- text : "Save configuration",
- handler : saveChanges
- }, delButton, '->', {
- text : 'Help',
- handler : function() {
- new tvheadend.help('DVR configuration', 'config_dvr.html');
- }
- } ]
- });
-
- function loadConfig() {
- confpanel.getForm().load({
- url : 'dvr',
- params : {
- 'op' : 'loadSettings',
- 'config_name' : confcombo.getValue()
- },
- success : function(form, action) {
- confpanel.enable();
- }
- });
- }
-
- confcombo.on('select', function() {
- if (confcombo.getValue() == '') delButton.disable();
- else delButton.enable();
- loadConfig();
- });
-
- confpanel.on('render', function() {
- loadConfig();
- });
-
- function saveChanges() {
- var config_name = confcombo.getValue();
- confpanel.getForm().submit({
- url : 'dvr',
- params : {
- 'op' : 'saveSettings',
- 'config_name' : config_name
- },
- waitMsg : 'Saving Data...',
- success : function(form, action) {
- confcombo.setValue(config_name);
- confcombo.fireEvent('select');
- },
- failure : function(form, action) {
- Ext.Msg.alert('Save failed', action.result.errormsg);
- }
- });
- }
-
- function deleteConfiguration() {
- if (confcombo.getValue() != "") {
- Ext.MessageBox.confirm('Message',
- 'Do you really want to delete DVR configuration \''
- + confcombo.getValue() + '\'?', deleteAction);
- }
- }
-
- function deleteAction(btn) {
- if (btn == 'yes') {
- confpanel.getForm().submit({
- url : 'dvr',
- params : {
- 'op' : 'deleteSettings',
- 'config_name' : confcombo.getValue()
- },
- waitMsg : 'Deleting Data...',
- success : function(form, action) {
- confcombo.setValue('');
- confcombo.fireEvent('select');
- },
- failure : function(form, action) {
- Ext.Msg.alert('Delete failed', action.result.errormsg);
- }
- });
- }
- }
-
- return confpanel;
-}
+ allowDecimals: false,
+ fieldLabel: 'Extra time after recordings (minutes)',
+ name: 'postExtraTime'
+ });
+
+ var postProcessing = new Ext.form.TextField({
+ width: 300,
+ fieldLabel: 'Post-processor command',
+ name: 'postproc'
+ });
+
+ /* Recording File Options */
+
+ var recordingPath = new Ext.form.TextField({
+ width: 300,
+ fieldLabel: 'Recording system path',
+ name: 'storage'
+ });
+
+ /* NB: recordingPermissions is defined as a TextField for validation purposes (leading zeros), but is ultimately a number */
+
+ var recordingPermissions = new Ext.form.TextField({
+ regex: /^[0][0-7]{3}$/,
+ maskRe: /[0-7]/,
+ width: 100,
+ allowBlank: false,
+ blankText: 'You must provide a value - use octal chmod notation, e.g. 0664',
+ fieldLabel: 'File permissions (octal, e.g. 0664)',
+ name: 'filePermissions'
+ });
+
+ /* TO DO - Add 'override user umask?' option, then trigger fchmod in mkmux.c, muxer_pass.c after file created */
+
+ var PATrewrite = new Ext.form.Checkbox({
+ fieldLabel: 'Rewrite PAT in passthrough mode',
+ name: 'rewritePAT'
+ });
+
+ var PMTrewrite = new Ext.form.Checkbox({
+ fieldLabel: 'Rewrite PMT in passthrough mode',
+ name: 'rewritePMT'
+ });
+
+ var tagMetadata = new Ext.form.Checkbox({
+ fieldLabel: 'Tag files with metadata',
+ name: 'tagFiles'
+ });
+
+ var skipCommercials = new Ext.form.Checkbox({
+ fieldLabel: 'Skip commercials',
+ name: 'commSkip'
+ });
+
+ /* Subdirectories and filename handling */
+
+ /* NB: directoryPermissions is defined as a TextField for validation purposes (leading zeros), but is ultimately a number */
+
+ var directoryPermissions = new Ext.form.TextField({
+ regex: /^[0][0-7]{3}$/,
+ maskRe: /[0-7]/,
+ width: 100,
+ allowBlank: false,
+ blankText: 'You must provide a value - use octal chmod notation, e.g. 0775',
+ fieldLabel: 'Directory permissions (octal, e.g. 0775)',
+ name: 'dirPermissions'
+ });
+
+ /* TO DO - Add 'override user umask?' option, then trigger fchmod in utils.c after directory created */
+
+ var dirsPerDay = new Ext.form.Checkbox({
+ fieldLabel: 'Make subdirectories per day',
+ name: 'dayDirs'
+ });
+
+ var dirsPerChannel = new Ext.form.Checkbox({
+ fieldLabel: 'Make subdirectories per channel',
+ name: 'channelDirs'
+ });
+
+ var dirsPerTitle = new Ext.form.Checkbox({
+ fieldLabel: 'Make subdirectories per title',
+ name: 'titleDirs'
+ });
+
+ var incChannelInTitle = new Ext.form.Checkbox({
+ fieldLabel: 'Include channel name in filename',
+ name: 'channelInTitle'
+ });
+
+ var incDateInTitle = new Ext.form.Checkbox({
+ fieldLabel: 'Include date in filename',
+ name: 'dateInTitle'
+ });
+
+ var incTimeInTitle = new Ext.form.Checkbox({
+ fieldLabel: 'Include time in filename',
+ name: 'timeInTitle'
+ });
+
+ var incEpisodeInTitle = new Ext.form.Checkbox({
+ fieldLabel: 'Include episode in filename',
+ name: 'episodeInTitle'
+ });
+
+ var incSubtitleInTitle = new Ext.form.Checkbox({
+ fieldLabel: 'Include subtitle in filename',
+ name: 'subtitleInTitle'
+ });
+
+ var episodeFirst = new Ext.form.Checkbox({
+ fieldLabel: 'Put episode in filename before date and time',
+ name: 'episodeBeforeDate'
+ });
+
+ var stripUnsafeChars = new Ext.form.Checkbox({
+ fieldLabel: 'Remove all unsafe characters from filename',
+ name: 'cleanTitle'
+ });
+
+ var stripWhitespace = new Ext.form.Checkbox({
+ fieldLabel: 'Replace whitespace in title with \'-\'',
+ name: 'whitespaceInTitle'
+ });
+
+
+ /* Sub-Panel - DVR behaviour */
+
+ var DVRBehaviour = new Ext.form.FieldSet({
+ title: 'DVR Behaviour',
+ width: 700,
+ autoHeight: true,
+ collapsible: true,
+ items: [recordingContainer, cacheScheme, logRetention, timeBefore, timeAfter, postProcessing]
+ });
+
+ /* Sub-Panel - File Output */
+
+ var FileOutputPanel = new Ext.form.FieldSet({
+ title: 'Recording File Options',
+ width: 700,
+ autoHeight: true,
+ collapsible: true,
+ items: [recordingPath, recordingPermissions, PATrewrite, PMTrewrite, tagMetadata, skipCommercials]
+ });
+
+ /* Sub-Panel - Directory operations */
+
+ var DirHandlingPanel = new Ext.form.FieldSet({
+ title: 'Subdirectory Options',
+ width: 700,
+ autoHeight: true,
+ collapsible: true,
+ items: [directoryPermissions, dirsPerDay, dirsPerChannel, dirsPerTitle]
+ });
+
+ /* Sub-Panel - File operations */
+
+ var FileHandlingPanel = new Ext.form.FieldSet({
+ title: 'Filename Options',
+ width: 700,
+ autoHeight: true,
+ collapsible: true,
+ items: [incChannelInTitle, incDateInTitle, incTimeInTitle, incEpisodeInTitle,
+ incSubtitleInTitle, episodeFirst, stripUnsafeChars, stripWhitespace]
+ });
+
+ /* Main (form) panel */
+
+ var confpanel = new Ext.FormPanel({
+ title: 'Digital Video Recorder',
+ iconCls: 'drive',
+ border: false,
+ bodyStyle: 'padding:15px',
+ anchor: '100% 50%',
+ labelAlign: 'right',
+ labelWidth: 250,
+ waitMsgTarget: true,
+ reader: confreader,
+ defaultType: 'textfield',
+ layout: 'form',
+ items: [DVRBehaviour, FileOutputPanel, DirHandlingPanel, FileHandlingPanel],
+ tbar: [confcombo, {
+ tooltip: 'Save changes made to dvr configuration below',
+ iconCls: 'save',
+ text: "Save configuration",
+ handler: saveChanges
+ }, delButton, '->', {
+ text: 'Help',
+ handler: function() {
+ new tvheadend.help('DVR configuration', 'config_dvr.html');
+ }
+ }]
+ });
+
+ function loadConfig() {
+ confpanel.getForm().load({
+ url: 'dvr',
+ params: {
+ 'op': 'loadSettings',
+ 'config_name': confcombo.getValue()
+ },
+ success: function(form, action) {
+ confpanel.enable();
+ }
+ });
+ }
+
+ confcombo.on('select', function() {
+ if (confcombo.getValue() === '')
+ delButton.disable();
+ else
+ delButton.enable();
+ loadConfig();
+ });
+
+ confpanel.on('render', function() {
+ loadConfig();
+ });
+
+ function saveChanges() {
+ var config_name = confcombo.getValue();
+ confpanel.getForm().submit({
+ url: 'dvr',
+ params: {
+ 'op': 'saveSettings',
+ 'config_name': config_name
+ },
+ waitMsg: 'Saving Data...',
+ success: function(form, action) {
+ confcombo.setValue(config_name);
+ confcombo.fireEvent('select');
+ },
+ failure: function(form, action) {
+ Ext.Msg.alert('Save failed', action.result.errormsg);
+ }
+ });
+ }
+
+ function deleteConfiguration() {
+ if (confcombo.getValue() !== "") {
+ Ext.MessageBox.confirm('Message',
+ 'Do you really want to delete DVR configuration \''
+ + confcombo.getValue() + '\'?', deleteAction);
+ }
+ }
+
+ function deleteAction(btn) {
+ if (btn === 'yes') {
+ confpanel.getForm().submit({
+ url: 'dvr',
+ params: {
+ 'op': 'deleteSettings',
+ 'config_name': confcombo.getValue()
+ },
+ waitMsg: 'Deleting Data...',
+ success: function(form, action) {
+ confcombo.setValue('');
+ confcombo.fireEvent('select');
+ },
+ failure: function(form, action) {
+ Ext.Msg.alert('Delete failed', action.result.errormsg);
+ }
+ });
+ }
+ }
+
+ return confpanel;
+};
tvheadend.brands = new Ext.data.JsonStore({
- root : 'entries',
- fields : [ 'uri', 'title' ],
- autoLoad : true,
- url : 'epgobject',
- baseParams : {
- op : 'brandList'
- }
+ root: 'entries',
+ fields: ['uri', 'title'],
+ autoLoad: true,
+ url: 'epgobject',
+ baseParams: {
+ op: 'brandList'
+ }
});
//WIBNI: might want this store to periodically update
tvheadend.ContentGroupStore = new Ext.data.JsonStore({
- root : 'entries',
- fields : [ 'name', 'code' ],
- autoLoad : true,
- url : 'ecglist'
+ root: 'entries',
+ fields: ['name', 'code'],
+ autoLoad: true,
+ url: 'ecglist'
});
tvheadend.contentGroupLookupName = function(code) {
- ret = "";
- tvheadend.ContentGroupStore.each(function(r) {
- if (r.data.code == code) ret = r.data.name;
- else if (ret == "" && r.data.code == (code & 0xF0)) ret = r.data.name;
- });
- return ret;
-}
+ ret = "";
+ tvheadend.ContentGroupStore.each(function(r) {
+ if (r.data.code === code)
+ ret = r.data.name;
+ else if (ret === "" && r.data.code === (code & 0xF0))
+ ret = r.data.name;
+ });
+ return ret;
+};
tvheadend.ContentGroupStore.setDefaultSort('code', 'ASC');
tvheadend.epgDetails = function(event) {
- var content = '';
-
- if (event.chicon != null && event.chicon.length > 0)
- content += '<img class="x-epg-chicon" src="'+ event.chicon + '">';
-
- content += '<div class="x-epg-title">' + event.title;
- if (event.subtitle)
- content += " : " + event.subtitle;
- content += '</div>';
- content += '<div class="x-epg-desc">' + event.episode + '</div>';
- content += '<div class="x-epg-desc">' + event.description + '</div>';
- content += '<div class="x-epg-meta">' + event.starrating + '</div>';
- content += '<div class="x-epg-meta">' + event.agerating + '</div>';
- content += '<div class="x-epg-meta">' + tvheadend.contentGroupLookupName(event.contenttype) + '</div>';
-
- if (event.ext_desc != null)
- content += '<div class="x-epg-meta">' + event.ext_desc + '</div>';
-
- if (event.ext_item != null)
- content += '<div class="x-epg-meta">' + event.ext_item + '</div>';
-
- if (event.ext_text != null)
- content += '<div class="x-epg-meta">' + event.ext_text + '</div>';
-
- content += '<div class="x-epg-meta"><a target="_blank" href="http://akas.imdb.com/find?q=' + event.title + '">Search IMDB</a></div>'
- content += '<div id="related"></div>';
- content += '<div id="altbcast"></div>';
-
- var confcombo = new Ext.form.ComboBox({
- store : tvheadend.configNames,
- triggerAction : 'all',
- mode : 'local',
- valueField : 'identifier',
- displayField : 'name',
- name : 'config_name',
- emptyText : '(default)',
- value : '',
- editable : false
- });
-
- var win = new Ext.Window({
- title : event.title,
- layout : 'fit',
- width : 500,
- height : 300,
- constrainHeader : true,
- buttons : [ confcombo, new Ext.Button({
- handler : recordEvent,
- text : "Record program"
- }), new Ext.Button({
- handler : recordSeries,
- text : event.serieslink ? "Record series" : "Autorec"
- }) ],
- buttonAlign : 'center',
- html : content
- });
- win.show();
-
- function recordEvent() {
- record('recordEvent');
- }
-
- function recordSeries() {
- record('recordSeries');
- }
-
- function record(op) {
- Ext.Ajax.request({
- url : 'dvr',
- params : {
- eventId : event.id,
- op : op,
- config_name : confcombo.getValue()
- },
-
- success : function(response, options) {
- win.close();
- },
-
- failure : function(response, options) {
- Ext.MessageBox.alert('DVR', response.statusText);
- }
- });
- }
-
- function showAlternatives(s) {
- var e = Ext.get('altbcast')
- html = '';
- if (s.getTotalCount() > 0) {
- html += '<div class="x-epg-subtitle">Alternative Broadcasts</div>';
- for (i = 0; i < s.getTotalCount(); i++) {
- var ab = s.getAt(i).data;
- var dt = Date.parseDate(ab.start, 'U');
- html += '<div class="x-epg-desc">' + dt.format('l H:i')
- + ' ' + ab.channel + '</div>';
- }
- }
- e.dom.innerHTML = html;
- }
- function showRelated(s) {
- var e = Ext.get('related')
- html = '';
- if (s.getTotalCount() > 0) {
- html += '<div class="x-epg-subtitle">Related Episodes</div>';
- for (i = 0; i < s.getTotalCount(); i++) {
- var ee = s.getAt(i).data;
- html += '<div class="x-epg-desc">';
- if (ee.episode) html += ee.episode + ' ';
- html += ee.title;
- if (ee.subtitle) html += ' : ' + ee.subtitle
- html += '</div>';
- }
- }
- e.dom.innerHTML = html;
- }
-
- var ab = new Ext.data.JsonStore({
- root : 'entries',
- url : 'epgrelated',
- autoLoad : false,
- id : 'id',
- baseParams : {
- op : 'get',
- id : event.id,
- type : 'alternative'
- },
- fields : Ext.data.Record.create([ 'id', 'channel', 'start' ]),
- listeners : {
- 'datachanged' : showAlternatives
- }
- });
- var re = new Ext.data.JsonStore({
- root : 'entries',
- url : 'epgrelated',
- autoLoad : false,
- id : 'uri',
- baseParams : {
- op : 'get',
- id : event.id,
- type : 'related'
- },
- fields : Ext.data.Record
- .create([ 'uri', 'title', 'subtitle', 'episode' ]),
- listeners : {
- 'datachanged' : showRelated
- }
- });
-}
+ var content = '';
+
+ if (event.chicon != null && event.chicon.length > 0)
+ content += '<img class="x-epg-chicon" src="' + event.chicon + '">';
+
+ content += '<div class="x-epg-title">' + event.title;
+ if (event.subtitle)
+ content += " : " + event.subtitle;
+ content += '</div>';
+ content += '<div class="x-epg-desc">' + event.episode + '</div>';
+ content += '<div class="x-epg-desc">' + event.description + '</div>';
+ content += '<div class="x-epg-meta">' + event.starrating + '</div>';
+ content += '<div class="x-epg-meta">' + event.agerating + '</div>';
+ content += '<div class="x-epg-meta">' + tvheadend.contentGroupLookupName(event.contenttype) + '</div>';
+
+ if (event.ext_desc != null)
+ content += '<div class="x-epg-meta">' + event.ext_desc + '</div>';
+
+ if (event.ext_item != null)
+ content += '<div class="x-epg-meta">' + event.ext_item + '</div>';
+
+ if (event.ext_text != null)
+ content += '<div class="x-epg-meta">' + event.ext_text + '</div>';
+
+ content += '<div class="x-epg-meta"><a target="_blank" href="http://akas.imdb.com/find?q=' + event.title + '">Search IMDB</a></div>';
+ content += '<div id="related"></div>';
+ content += '<div id="altbcast"></div>';
+
+ var confcombo = new Ext.form.ComboBox({
+ store: tvheadend.configNames,
+ triggerAction: 'all',
+ mode: 'local',
+ valueField: 'identifier',
+ displayField: 'name',
+ name: 'config_name',
+ emptyText: '(default)',
+ value: '',
+ editable: false
+ });
+
+ var win = new Ext.Window({
+ title: event.title,
+ layout: 'fit',
+ width: 500,
+ height: 300,
+ constrainHeader: true,
+ buttons: [confcombo, new Ext.Button({
+ handler: recordEvent,
+ text: "Record program"
+ }), new Ext.Button({
+ handler: recordSeries,
+ text: event.serieslink ? "Record series" : "Autorec"
+ })],
+ buttonAlign: 'center',
+ html: content
+ });
+ win.show();
+
+ function recordEvent() {
+ record('recordEvent');
+ }
+
+ function recordSeries() {
+ record('recordSeries');
+ }
+
+ function record(op) {
+ Ext.Ajax.request({
+ url: 'dvr',
+ params: {
+ eventId: event.id,
+ op: op,
+ config_name: confcombo.getValue()
+ },
+ success: function(response, options) {
+ win.close();
+ },
+ failure: function(response, options) {
+ Ext.MessageBox.alert('DVR', response.statusText);
+ }
+ });
+ }
+
+ function showAlternatives(s) {
+ var e = Ext.get('altbcast');
+ html = '';
+ if (s.getTotalCount() > 0) {
+ html += '<div class="x-epg-subtitle">Alternative Broadcasts</div>';
+ for (i = 0; i < s.getTotalCount(); i++) {
+ var ab = s.getAt(i).data;
+ var dt = Date.parseDate(ab.start, 'U');
+ html += '<div class="x-epg-desc">' + dt.format('l H:i')
+ + ' ' + ab.channel + '</div>';
+ }
+ }
+ e.dom.innerHTML = html;
+ }
+ function showRelated(s) {
+ var e = Ext.get('related');
+ html = '';
+ if (s.getTotalCount() > 0) {
+ html += '<div class="x-epg-subtitle">Related Episodes</div>';
+ for (i = 0; i < s.getTotalCount(); i++) {
+ var ee = s.getAt(i).data;
+ html += '<div class="x-epg-desc">';
+ if (ee.episode)
+ html += ee.episode + ' ';
+ html += ee.title;
+ if (ee.subtitle)
+ html += ' : ' + ee.subtitle;
+ html += '</div>';
+ }
+ }
+ e.dom.innerHTML = html;
+ }
+
+ var ab = new Ext.data.JsonStore({
+ root: 'entries',
+ url: 'epgrelated',
+ autoLoad: false,
+ id: 'id',
+ baseParams: {
+ op: 'get',
+ id: event.id,
+ type: 'alternative'
+ },
+ fields: Ext.data.Record.create(['id', 'channel', 'start']),
+ listeners: {
+ 'datachanged': showAlternatives
+ }
+ });
+ var re = new Ext.data.JsonStore({
+ root: 'entries',
+ url: 'epgrelated',
+ autoLoad: false,
+ id: 'uri',
+ baseParams: {
+ op: 'get',
+ id: event.id,
+ type: 'related'
+ },
+ fields: Ext.data.Record
+ .create(['uri', 'title', 'subtitle', 'episode']),
+ listeners: {
+ 'datachanged': showRelated
+ }
+ });
+};
tvheadend.epg = function() {
- var xg = Ext.grid;
-
- var actions = new Ext.ux.grid.RowActions({
- header : '',
- width : 20,
- dataIndex : 'actions',
- actions : [ {
- iconIndex : 'schedstate'
- } ]
- });
-
- var epgStore = new Ext.ux.grid.livegrid.Store({
- autoLoad : true,
- url : 'epg',
- bufferSize : 300,
- reader : new Ext.ux.grid.livegrid.JsonReader({
- root : 'entries',
- totalProperty : 'totalCount',
- id : 'id'
- }, [ {
- name : 'id'
- }, {
- name : 'channel'
- }, {
- name : 'channelid'
- }, {
- name : 'title'
- }, {
- name : 'subtitle'
- }, {
- name : 'episode'
- }, {
- name : 'description'
- }, {
- name : 'chicon'
- }, {
- name : 'start',
- type : 'date',
- dateFormat : 'U' /* unix time */
- }, {
- name : 'end',
- type : 'date',
- dateFormat : 'U' /* unix time */
- }, {
- name : 'duration'
- }, {
- name : 'starrating'
- }, {
- name : 'agerating'
- }, {
- name : 'contenttype'
- }, {
- name : 'schedstate'
- }, {
- name : 'serieslink'
- } ])
- });
-
- function setMetaAttr(meta, record) {
- var now = new Date;
- var start = record.get('start');
-
- if (now.getTime() > start.getTime()) {
- meta.attr = 'style="font-weight:bold;"';
- }
- }
-
- function renderDate(value, meta, record, rowIndex, colIndex, store) {
- setMetaAttr(meta, record);
-
- var dt = new Date(value);
- return dt.format('D, M d, H:i');
- }
-
- function renderDuration(value, meta, record, rowIndex, colIndex, store) {
- setMetaAttr(meta, record);
-
- value = Math.floor(value / 60);
-
- if (value >= 60) {
- var min = value % 60;
- var hours = Math.floor(value / 60);
-
- if (min == 0) {
- return hours + ' hrs';
- }
- return hours + ' hrs, ' + min + ' min';
- }
- else {
- return value + ' min';
- }
- }
+ var xg = Ext.grid;
+
+ var actions = new Ext.ux.grid.RowActions({
+ header: '',
+ width: 20,
+ dataIndex: 'actions',
+ actions: [{
+ iconIndex: 'schedstate'
+ }]
+ });
+
+ var epgStore = new Ext.ux.grid.livegrid.Store({
+ autoLoad: true,
+ url: 'epg',
+ bufferSize: 300,
+ reader: new Ext.ux.grid.livegrid.JsonReader({
+ root: 'entries',
+ totalProperty: 'totalCount',
+ id: 'id'
+ }, [{
+ name: 'id'
+ }, {
+ name: 'channel'
+ }, {
+ name: 'channelid'
+ }, {
+ name: 'title'
+ }, {
+ name: 'subtitle'
+ }, {
+ name: 'episode'
+ }, {
+ name: 'description'
+ }, {
+ name: 'chicon'
+ }, {
+ name: 'start',
+ type: 'date',
+ dateFormat: 'U' /* unix time */
+ }, {
+ name: 'end',
+ type: 'date',
+ dateFormat: 'U' /* unix time */
+ }, {
+ name: 'duration'
+ }, {
+ name: 'starrating'
+ }, {
+ name: 'agerating'
+ }, {
+ name: 'contenttype'
+ }, {
+ name: 'schedstate'
+ }, {
+ name: 'serieslink'
+ }])
+ });
+
+ function setMetaAttr(meta, record) {
+ var now = new Date;
+ var start = record.get('start');
+
+ if (now.getTime() > start.getTime()) {
+ meta.attr = 'style="font-weight:bold;"';
+ }
+ }
+
+ function renderDate(value, meta, record, rowIndex, colIndex, store) {
+ setMetaAttr(meta, record);
+
+ var dt = new Date(value);
+ return dt.format('D, M d, H:i');
+ }
+
+ function renderDuration(value, meta, record, rowIndex, colIndex, store) {
+ setMetaAttr(meta, record);
+
+ value = Math.floor(value / 60);
+
+ if (value >= 60) {
+ var min = value % 60;
+ var hours = Math.floor(value / 60);
+
+ if (min === 0) {
+ return hours + ' hrs';
+ }
+ return hours + ' hrs, ' + min + ' min';
+ }
+ else {
+ return value + ' min';
+ }
+ }
function renderText(value, meta, record, rowIndex, colIndex, store) {
setMetaAttr(meta, record);
return '' + value;
}
- var epgCm = new Ext.grid.ColumnModel([ actions, {
- width : 250,
- id : 'title',
- header : "Title",
- dataIndex : 'title',
- renderer : renderText
- }, {
- width : 250,
- id : 'subtitle',
- header : "SubTitle",
- dataIndex : 'subtitle',
- renderer : renderText
- }, {
- width : 100,
- id : 'episode',
- header : "Episode",
- dataIndex : 'episode',
- renderer : renderText
- }, {
- width : 100,
- id : 'start',
- header : "Start",
- dataIndex : 'start',
- renderer : renderDate
- }, {
- width : 100,
- hidden : true,
- id : 'end',
- header : "End",
- dataIndex : 'end',
- renderer : renderDate
- }, {
- width : 100,
- id : 'duration',
- header : "Duration",
- dataIndex : 'duration',
- renderer : renderDuration
- }, {
- width : 250,
- id : 'channel',
- header : "Channel",
- dataIndex : 'channel',
- renderer : renderText
- }, {
- width : 50,
- id : 'starrating',
- header : "Stars",
- dataIndex : 'starrating',
- renderer : renderInt
- }, {
- width : 50,
- id : 'agerating',
- header : "Age",
- dataIndex : 'agerating',
- renderer : renderInt
- }, {
- width : 250,
- id : 'contenttype',
- header : "Content Type",
- dataIndex : 'contenttype',
- renderer : function(v) {
- return tvheadend.contentGroupLookupName(v);
- }
- } ]);
-
- // Title search box
-
- var epgFilterTitle = new Ext.form.TextField({
- emptyText : 'Search title...',
- width : 200
- });
-
- // Channels, uses global store
-
- var epgFilterChannels = new Ext.form.ComboBox({
- loadingText : 'Loading...',
- width : 200,
- displayField : 'val',
- store : tvheadend.channels,
- mode : 'local',
- editable : true,
- forceSelection: true,
- triggerAction : 'all',
- emptyText : 'Filter channel...'
- });
-
- // Tags, uses global store
-
- var epgFilterChannelTags = new Ext.form.ComboBox({
- width : 200,
- displayField : 'name',
- store : tvheadend.channelTags,
- mode : 'local',
- editable : true,
- forceSelection: true,
- triggerAction : 'all',
- emptyText : 'Filter tag...'
- });
-
- // Content groups
-
- var epgFilterContentGroup = new Ext.form.ComboBox({
- loadingText : 'Loading...',
- width : 200,
- displayField : 'name',
- store : tvheadend.ContentGroupStore,
- mode : 'local',
- editable : true,
- forceSelection: true,
- triggerAction : 'all',
- emptyText : 'Filter content type...'
- });
-
- function epgQueryClear() {
- delete epgStore.baseParams.channel;
- delete epgStore.baseParams.tag;
- delete epgStore.baseParams.contenttype;
- delete epgStore.baseParams.title;
-
- epgFilterChannels.setValue("");
- epgFilterChannelTags.setValue("");
- epgFilterContentGroup.setValue("");
- epgFilterTitle.setValue("");
-
- epgStore.reload();
- }
-
- epgFilterChannels.on('select', function(c, r) {
- if (epgStore.baseParams.channel != r.data.key) {
- epgStore.baseParams.channel = r.data.key;
- epgStore.reload();
- }
- });
-
- epgFilterChannelTags.on('select', function(c, r) {
- if (epgStore.baseParams.tag != r.data.name) {
- epgStore.baseParams.tag = r.data.name;
- epgStore.reload();
- }
- });
-
- epgFilterContentGroup.on('select', function(c, r) {
- if (epgStore.baseParams.contenttype != r.data.code) {
- epgStore.baseParams.contenttype = r.data.code;
- epgStore.reload();
- }
- });
-
- epgFilterTitle.on('valid', function(c) {
- var value = c.getValue();
-
- if (value.length < 1) value = null;
-
- if (epgStore.baseParams.title != value) {
- epgStore.baseParams.title = value;
- epgStore.reload();
- }
- });
-
- var epgView = new Ext.ux.grid.livegrid.GridView({
- nearLimit : 100,
- loadMask : {
- msg : 'Buffering. Please wait...'
- }
- });
-
- var panel = new Ext.ux.grid.livegrid.GridPanel({
- stateful: true,
- stateId : 'epggrid',
- enableDragDrop : false,
- cm : epgCm,
- plugins : [ actions ],
- title : 'Electronic Program Guide',
- iconCls : 'newspaper',
- store : epgStore,
- selModel : new Ext.ux.grid.livegrid.RowSelectionModel(),
- view : epgView,
- tbar : [
- epgFilterTitle,
- '-',
- epgFilterChannels,
- '-',
- epgFilterChannelTags,
- '-',
- epgFilterContentGroup,
- '-',
- {
- text : 'Reset',
- handler : epgQueryClear
- },
- '->',
- {
- text : 'Watch TV',
- iconCls : 'eye',
- handler : function() {
- new tvheadend.VideoPlayer();
- }
- },
- '-',
- {
- text : 'Create AutoRec',
- iconCls : 'wand',
- tooltip : 'Create an automatic recording entry that will '
- + 'record all future programmes that matches '
- + 'the current query.',
- handler : createAutoRec
- }, '-', {
- text : 'Help',
- handler : function() {
- new tvheadend.help('Electronic Program Guide', 'epg.html');
- }
- } ],
-
- bbar : new Ext.ux.grid.livegrid.Toolbar({
- view : epgView,
- displayInfo : true
- })
- });
-
- panel.on('rowclick', rowclicked);
-
- function rowclicked(grid, index) {
- new tvheadend.epgDetails(grid.getStore().getAt(index).data);
- }
-
- function createAutoRec() {
-
- var title = epgStore.baseParams.title ? epgStore.baseParams.title
- : "<i>Don't care</i>";
- var channel = epgStore.baseParams.channel ? epgStore.baseParams.channel
- : "<i>Don't care</i>";
- var tag = epgStore.baseParams.tag ? epgStore.baseParams.tag
- : "<i>Don't care</i>";
- var contenttype = epgStore.baseParams.contenttype ? epgStore.baseParams.contenttype
- : "<i>Don't care</i>";
-
- Ext.MessageBox.confirm('Auto Recorder',
- 'This will create an automatic rule that '
- + 'continuously scans the EPG for programmes '
- + 'to record that matches this query: ' + '<br><br>'
- + '<div class="x-smallhdr">Title:</div>' + title + '<br>'
- + '<div class="x-smallhdr">Channel:</div>' + channel + '<br>'
- + '<div class="x-smallhdr">Tag:</div>' + tag + '<br>'
- + '<div class="x-smallhdr">Genre:</div>' + contenttype + '<br>'
- + '<br>' + 'Currently this will match (and record) '
- + epgStore.getTotalCount() + ' events. ' + 'Are you sure?',
-
- function(button) {
- if (button == 'no') return;
- createAutoRec2(epgStore.baseParams);
- });
- }
-
- function createAutoRec2(params) {
- /* Really do it */
- params.op = 'createAutoRec';
- Ext.Ajax.request({
- url : 'dvr',
- params : params
- });
- }
-
- return panel;
-}
+ var epgCm = new Ext.grid.ColumnModel([actions, {
+ width: 250,
+ id: 'title',
+ header: "Title",
+ dataIndex: 'title',
+ renderer: renderText
+ }, {
+ width: 250,
+ id: 'subtitle',
+ header: "SubTitle",
+ dataIndex: 'subtitle',
+ renderer: renderText
+ }, {
+ width: 100,
+ id: 'episode',
+ header: "Episode",
+ dataIndex: 'episode',
+ renderer: renderText
+ }, {
+ width: 100,
+ id: 'start',
+ header: "Start",
+ dataIndex: 'start',
+ renderer: renderDate
+ }, {
+ width: 100,
+ hidden: true,
+ id: 'end',
+ header: "End",
+ dataIndex: 'end',
+ renderer: renderDate
+ }, {
+ width: 100,
+ id: 'duration',
+ header: "Duration",
+ dataIndex: 'duration',
+ renderer: renderDuration
+ }, {
+ width: 250,
+ id: 'channel',
+ header: "Channel",
+ dataIndex: 'channel',
+ renderer: renderText
+ }, {
+ width: 50,
+ id: 'starrating',
+ header: "Stars",
+ dataIndex: 'starrating',
+ renderer: renderInt
+ }, {
+ width: 50,
+ id: 'agerating',
+ header: "Age",
+ dataIndex: 'agerating',
+ renderer: renderInt
+ }, {
+ width: 250,
+ id: 'contenttype',
+ header: "Content Type",
+ dataIndex: 'contenttype',
+ renderer: function(v) {
+ return tvheadend.contentGroupLookupName(v);
+ }
+ }]);
+
+ // Title search box
+
+ var epgFilterTitle = new Ext.form.TextField({
+ emptyText: 'Search title...',
+ width: 200
+ });
+
+ // Channels, uses global store
+
+ var epgFilterChannels = new Ext.form.ComboBox({
+ loadingText: 'Loading...',
+ width: 200,
+ displayField: 'val',
+ store: tvheadend.channels,
+ mode: 'local',
+ editable: true,
+ forceSelection: true,
+ triggerAction: 'all',
+ emptyText: 'Filter channel...'
+ });
+
+ // Tags, uses global store
+
+ var epgFilterChannelTags = new Ext.form.ComboBox({
+ width: 200,
+ displayField: 'name',
+ store: tvheadend.channelTags,
+ mode: 'local',
+ editable: true,
+ forceSelection: true,
+ triggerAction: 'all',
+ emptyText: 'Filter tag...'
+ });
+
+ // Content groups
+
+ var epgFilterContentGroup = new Ext.form.ComboBox({
+ loadingText: 'Loading...',
+ width: 200,
+ displayField: 'name',
+ store: tvheadend.ContentGroupStore,
+ mode: 'local',
+ editable: true,
+ forceSelection: true,
+ triggerAction: 'all',
+ emptyText: 'Filter content type...'
+ });
+
+ function epgQueryClear() {
+ delete epgStore.baseParams.channel;
+ delete epgStore.baseParams.tag;
+ delete epgStore.baseParams.contenttype;
+ delete epgStore.baseParams.title;
+
+ epgFilterChannels.setValue("");
+ epgFilterChannelTags.setValue("");
+ epgFilterContentGroup.setValue("");
+ epgFilterTitle.setValue("");
+
+ epgStore.reload();
+ }
+
+ epgFilterChannels.on('select', function(c, r) {
+ if (epgStore.baseParams.channel !== r.data.key) {
+ epgStore.baseParams.channel = r.data.key;
+ epgStore.reload();
+ }
+ });
+
+ epgFilterChannelTags.on('select', function(c, r) {
+ if (epgStore.baseParams.tag !== r.data.name) {
+ epgStore.baseParams.tag = r.data.name;
+ epgStore.reload();
+ }
+ });
+
+ epgFilterContentGroup.on('select', function(c, r) {
+ if (epgStore.baseParams.contenttype !== r.data.code) {
+ epgStore.baseParams.contenttype = r.data.code;
+ epgStore.reload();
+ }
+ });
+
+ epgFilterTitle.on('valid', function(c) {
+ var value = c.getValue();
+
+ if (value.length < 1)
+ value = null;
+
+ if (epgStore.baseParams.title !== value) {
+ epgStore.baseParams.title = value;
+ epgStore.reload();
+ }
+ });
+
+ var epgView = new Ext.ux.grid.livegrid.GridView({
+ nearLimit: 100,
+ loadMask: {
+ msg: 'Buffering. Please wait...'
+ }
+ });
+
+ var panel = new Ext.ux.grid.livegrid.GridPanel({
+ stateful: true,
+ stateId: 'epggrid',
+ enableDragDrop: false,
+ cm: epgCm,
+ plugins: [actions],
+ title: 'Electronic Program Guide',
+ iconCls: 'newspaper',
+ store: epgStore,
+ selModel: new Ext.ux.grid.livegrid.RowSelectionModel(),
+ view: epgView,
+ tbar: [
+ epgFilterTitle,
+ '-',
+ epgFilterChannels,
+ '-',
+ epgFilterChannelTags,
+ '-',
+ epgFilterContentGroup,
+ '-',
+ {
+ text: 'Reset',
+ handler: epgQueryClear
+ },
+ '->',
+ {
+ text: 'Watch TV',
+ iconCls: 'eye',
+ handler: function() {
+ new tvheadend.VideoPlayer();
+ }
+ },
+ '-',
+ {
+ text: 'Create AutoRec',
+ iconCls: 'wand',
+ tooltip: 'Create an automatic recording entry that will '
+ + 'record all future programmes that matches '
+ + 'the current query.',
+ handler: createAutoRec
+ }, '-', {
+ text: 'Help',
+ handler: function() {
+ new tvheadend.help('Electronic Program Guide', 'epg.html');
+ }
+ }],
+ bbar: new Ext.ux.grid.livegrid.Toolbar({
+ view: epgView,
+ displayInfo: true
+ })
+ });
+
+ panel.on('rowclick', rowclicked);
+
+ function rowclicked(grid, index) {
+ new tvheadend.epgDetails(grid.getStore().getAt(index).data);
+ }
+
+ function createAutoRec() {
+
+ var title = epgStore.baseParams.title ? epgStore.baseParams.title
+ : "<i>Don't care</i>";
+ var channel = epgStore.baseParams.channel ? epgStore.baseParams.channel
+ : "<i>Don't care</i>";
+ var tag = epgStore.baseParams.tag ? epgStore.baseParams.tag
+ : "<i>Don't care</i>";
+ var contenttype = epgStore.baseParams.contenttype ? epgStore.baseParams.contenttype
+ : "<i>Don't care</i>";
+
+ Ext.MessageBox.confirm('Auto Recorder',
+ 'This will create an automatic rule that '
+ + 'continuously scans the EPG for programmes '
+ + 'to record that matches this query: ' + '<br><br>'
+ + '<div class="x-smallhdr">Title:</div>' + title + '<br>'
+ + '<div class="x-smallhdr">Channel:</div>' + channel + '<br>'
+ + '<div class="x-smallhdr">Tag:</div>' + tag + '<br>'
+ + '<div class="x-smallhdr">Genre:</div>' + contenttype + '<br>'
+ + '<br>' + 'Currently this will match (and record) '
+ + epgStore.getTotalCount() + ' events. ' + 'Are you sure?',
+ function(button) {
+ if (button === 'no')
+ return;
+ createAutoRec2(epgStore.baseParams);
+ });
+ }
+
+ function createAutoRec2(params) {
+ /* Really do it */
+ params.op = 'createAutoRec';
+ Ext.Ajax.request({
+ url: 'dvr',
+ params: params
+ });
+ }
+
+ return panel;
+};
tvheadend.epggrabChannels = new Ext.data.JsonStore({
- root : 'entries',
- url : 'epggrab',
- baseParams : {
- op : 'channelList'
- },
- fields : [ 'id', 'mod', 'name', 'icon', 'number', 'channel', 'mod-id',
- 'mod-name' ]
+ root: 'entries',
+ url: 'epggrab',
+ baseParams: {
+ op: 'channelList'
+ },
+ fields: ['id', 'mod', 'name', 'icon', 'number', 'channel', 'mod-id',
+ 'mod-name']
});
tvheadend.epggrab = function() {
- /* ****************************************************************
- * Data
- * ***************************************************************/
-
- /*
- * Module lists (I'm sure there is a better way!)
- */
- var EPGGRAB_MODULE_INTERNAL = "internal";
- var EPGGRAB_MODULE_EXTERNAL = "external";
- var EPGGRAB_MODULE_OTA = "ota";
-
- var moduleStore = new Ext.data.JsonStore({
- root : 'entries',
- url : 'epggrab',
- baseParams : {
- op : 'moduleList'
- },
- autoLoad : true,
- fields : [ 'id', 'name', 'path', 'type', 'enabled' ]
- });
- var internalModuleStore = new Ext.data.Store({
- recordType : moduleStore.recordType
- });
- var externalModuleStore = new Ext.data.Store({
- recordType : moduleStore.recordType
- });
- var otaModuleStore = new Ext.data.Store({
- recordType : moduleStore.recordType
- });
- moduleStore.on('load', function() {
- moduleStore.filterBy(function(r) {
- return r.get('type') == EPGGRAB_MODULE_INTERNAL;
- });
- r = new internalModuleStore.recordType({
- id : '',
- name : 'Disabled'
- });
- internalModuleStore.add(r);
- moduleStore.each(function(r) {
- internalModuleStore.add(r.copy());
- });
- moduleStore.filterBy(function(r) {
- return r.get('type') == EPGGRAB_MODULE_EXTERNAL;
- });
- moduleStore.each(function(r) {
- externalModuleStore.add(r.copy());
- });
- moduleStore.filterBy(function(r) {
- return r.get('type') == EPGGRAB_MODULE_OTA;
- });
- moduleStore.each(function(r) {
- otaModuleStore.add(r.copy());
- });
- moduleStore.filterBy(function(r) {
- return r.get('type') != EPGGRAB_MODULE_INTERNAL;
- });
- });
-
- /* Enable module in one of the stores (will auto update primary) */
- function moduleSelect(r, e) {
- r.set('enabled', e);
- t = moduleStore.getById(r.id);
- if (t) t.set('enabled', e);
- }
-
- /*
- * Basic Config
- */
-
- var confreader = new Ext.data.JsonReader({
- root : 'epggrabSettings'
- }, [ 'module', 'interval', 'channel_rename', 'channel_renumber',
- 'channel_reicon', 'epgdb_periodicsave' ]);
-
- /* ****************************************************************
- * Basic Fields
- * ***************************************************************/
-
- /*
- * Module selector
- */
- var internalModule = new Ext.form.ComboBox({
- fieldLabel : 'Module',
- hiddenName : 'module',
- width : 300,
- valueField : 'id',
- displayField : 'name',
- forceSelection : true,
- editable : false,
- mode : 'local',
- triggerAction : 'all',
- store : internalModuleStore
- });
-
- /*
- * Interval selector
- */
- var intervalUnits = [ [ 86400, 'Days' ], [ 3600, 'Hours' ],
- [ 60, 'Minutes' ], [ 1, 'Seconds' ] ];
- var intervalValue = new Ext.form.NumberField({
- width : 300,
- allowNegative : false,
- allowDecimals : false,
- minValue : 1,
- maxValue : 7,
- value : 1,
- fieldLabel : 'Grab interval',
- name : 'intervalValue',
- listeners : {
- 'valid' : function(e) {
- v = e.getValue() * intervalUnit.getValue();
- interval.setValue(v);
- }
- }
- })
- var intervalUnit = new Ext.form.ComboBox({
- name : 'intervalUnit',
- width : 300,
- valueField : 'key',
- displayField : 'value',
- value : 86400,
- forceSelection : true,
- editable : false,
- triggerAction : 'all',
- mode : 'local',
- store : new Ext.data.SimpleStore({
- fields : [ 'key', 'value' ],
- data : intervalUnits
- }),
- listeners : {
- 'change' : function(e, n, o) {
- intervalValue.maxValue = (7 * 86400) / n;
- intervalValue.validate();
- }
- }
- });
- var interval = new Ext.form.Hidden({
- name : 'interval',
- value : 86400,
- listeners : {
- 'enable' : function(e) {
- v = e.getValue();
- for (i = 0; i < intervalUnits.length; i++) {
- u = intervalUnits[i][0];
- if ((v % u) == 0) {
- intervalUnit.setValue(u);
- intervalValue.maxValue = (7 * 86400) / u;
- intervalValue.setValue(v / u);
- intervalValue.validate();
- break;
- }
- }
- }
- }
- });
-
- /*
- * Channel handling
- */
- var channelRename = new Ext.form.Checkbox({
- name : 'channel_rename',
- fieldLabel : 'Update channel name'
- });
-
- var channelRenumber = new Ext.form.Checkbox({
- name : 'channel_renumber',
- fieldLabel : 'Update channel number'
- });
-
- var channelReicon = new Ext.form.Checkbox({
- name : 'channel_reicon',
- fieldLabel : 'Update channel icon'
- });
-
- var epgPeriodicSave = new Ext.form.NumberField({
- width : 30,
- allowNegative : false,
- allowDecimals : false,
- minValue : 0,
- maxValue : 24,
- value : 0,
- fieldLabel : 'Periodic save EPG to disk',
- name : 'epgdb_periodicsave',
+ /* ****************************************************************
+ * Data
+ * ***************************************************************/
+
+ /*
+ * Module lists (I'm sure there is a better way!)
+ */
+ var EPGGRAB_MODULE_INTERNAL = "internal";
+ var EPGGRAB_MODULE_EXTERNAL = "external";
+ var EPGGRAB_MODULE_OTA = "ota";
+
+ var moduleStore = new Ext.data.JsonStore({
+ root: 'entries',
+ url: 'epggrab',
+ baseParams: {
+ op: 'moduleList'
+ },
+ autoLoad: true,
+ fields: ['id', 'name', 'path', 'type', 'enabled']
+ });
+ var internalModuleStore = new Ext.data.Store({
+ recordType: moduleStore.recordType
+ });
+ var externalModuleStore = new Ext.data.Store({
+ recordType: moduleStore.recordType
+ });
+ var otaModuleStore = new Ext.data.Store({
+ recordType: moduleStore.recordType
+ });
+ moduleStore.on('load', function() {
+ moduleStore.filterBy(function(r) {
+ return r.get('type') === EPGGRAB_MODULE_INTERNAL;
});
+ r = new internalModuleStore.recordType({
+ id: '',
+ name: 'Disabled'
+ });
+ internalModuleStore.add(r);
+ moduleStore.each(function(r) {
+ internalModuleStore.add(r.copy());
+ });
+ moduleStore.filterBy(function(r) {
+ return r.get('type') === EPGGRAB_MODULE_EXTERNAL;
+ });
+ moduleStore.each(function(r) {
+ externalModuleStore.add(r.copy());
+ });
+ moduleStore.filterBy(function(r) {
+ return r.get('type') === EPGGRAB_MODULE_OTA;
+ });
+ moduleStore.each(function(r) {
+ otaModuleStore.add(r.copy());
+ });
+ moduleStore.filterBy(function(r) {
+ return r.get('type') !== EPGGRAB_MODULE_INTERNAL;
+ });
+ });
+
+ /* Enable module in one of the stores (will auto update primary) */
+ function moduleSelect(r, e) {
+ r.set('enabled', e);
+ t = moduleStore.getById(r.id);
+ if (t)
+ t.set('enabled', e);
+ }
+
+ /*
+ * Basic Config
+ */
+
+ var confreader = new Ext.data.JsonReader({
+ root: 'epggrabSettings'
+ }, ['module', 'interval', 'channel_rename', 'channel_renumber',
+ 'channel_reicon', 'epgdb_periodicsave']);
+
+ /* ****************************************************************
+ * Basic Fields
+ * ***************************************************************/
+
+ /*
+ * Module selector
+ */
+ var internalModule = new Ext.form.ComboBox({
+ fieldLabel: 'Module',
+ hiddenName: 'module',
+ width: 300,
+ valueField: 'id',
+ displayField: 'name',
+ forceSelection: true,
+ editable: false,
+ mode: 'local',
+ triggerAction: 'all',
+ store: internalModuleStore
+ });
+
+ /*
+ * Interval selector
+ */
+ var intervalUnits = [[86400, 'Days'], [3600, 'Hours'],
+ [60, 'Minutes'], [1, 'Seconds']];
+ var intervalValue = new Ext.form.NumberField({
+ width: 300,
+ allowNegative: false,
+ allowDecimals: false,
+ minValue: 1,
+ maxValue: 7,
+ value: 1,
+ fieldLabel: 'Grab interval',
+ name: 'intervalValue',
+ listeners: {
+ 'valid': function(e) {
+ v = e.getValue() * intervalUnit.getValue();
+ interval.setValue(v);
+ }
+ }
+ });
+ var intervalUnit = new Ext.form.ComboBox({
+ name: 'intervalUnit',
+ width: 300,
+ valueField: 'key',
+ displayField: 'value',
+ value: 86400,
+ forceSelection: true,
+ editable: false,
+ triggerAction: 'all',
+ mode: 'local',
+ store: new Ext.data.SimpleStore({
+ fields: ['key', 'value'],
+ data: intervalUnits
+ }),
+ listeners: {
+ 'change': function(e, n, o) {
+ intervalValue.maxValue = (7 * 86400) / n;
+ intervalValue.validate();
+ }
+ }
+ });
+ var interval = new Ext.form.Hidden({
+ name: 'interval',
+ value: 86400,
+ listeners: {
+ 'enable': function(e) {
+ v = e.getValue();
+ for (i = 0; i < intervalUnits.length; i++) {
+ u = intervalUnits[i][0];
+ if ((v % u) === 0) {
+ intervalUnit.setValue(u);
+ intervalValue.maxValue = (7 * 86400) / u;
+ intervalValue.setValue(v / u);
+ intervalValue.validate();
+ break;
+ }
+ }
+ }
+ }
+ });
+
+ /*
+ * Channel handling
+ */
+ var channelRename = new Ext.form.Checkbox({
+ name: 'channel_rename',
+ fieldLabel: 'Update channel name'
+ });
+
+ var channelRenumber = new Ext.form.Checkbox({
+ name: 'channel_renumber',
+ fieldLabel: 'Update channel number'
+ });
+
+ var channelReicon = new Ext.form.Checkbox({
+ name: 'channel_reicon',
+ fieldLabel: 'Update channel icon'
+ });
+
+ var epgPeriodicSave = new Ext.form.NumberField({
+ width: 30,
+ allowNegative: false,
+ allowDecimals: false,
+ minValue: 0,
+ maxValue: 24,
+ value: 0,
+ fieldLabel: 'Periodic save EPG to disk',
+ name: 'epgdb_periodicsave'
+ });
+
+ /*
+ * Simple fields
+ */
+ var simplePanel = new Ext.form.FieldSet({
+ title: 'General Config',
+ width: 700,
+ autoHeight: true,
+ collapsible: true,
+ items: [channelRename, channelRenumber, channelReicon, epgPeriodicSave]
+ });
+
+ /*
+ * Internal grabber
+ */
+ var internalPanel = new Ext.form.FieldSet({
+ title: 'Internal Grabber',
+ width: 700,
+ autoHeight: true,
+ collapsible: true,
+ items: [interval, internalModule, intervalValue, intervalUnit]
+ });
+
+ /* ****************************************************************
+ * Advanced Fields
+ * ***************************************************************/
+
+ /*
+ * External modules
+ */
+ var externalSelectionModel = new Ext.grid.CheckboxSelectionModel({
+ singleSelect: false,
+ listeners: {
+ 'rowselect': function(s, ri, r) {
+ moduleSelect(r, 1);
+ },
+ 'rowdeselect': function(s, ri, r) {
+ moduleSelect(r, 0);
+ }
+ }
+ });
+
+ var externalColumnModel = new Ext.grid.ColumnModel([externalSelectionModel,
+ {
+ header: 'Module',
+ dataIndex: 'name',
+ width: 200,
+ sortable: false
+ }, {
+ header: 'Path',
+ dataIndex: 'path',
+ width: 300,
+ sortable: false
+ }]);
+
+ var externalGrid = new Ext.grid.EditorGridPanel({
+ store: externalModuleStore,
+ cm: externalColumnModel,
+ sm: externalSelectionModel,
+ width: 600,
+ height: 150,
+ frame: false,
+ viewConfig: {
+ forceFit: true
+ },
+ iconCls: 'icon-grid'
+ });
+
+ var externalPanel = new Ext.form.FieldSet({
+ title: 'External Interfaces',
+ width: 700,
+ autoHeight: true,
+ collapsible: true,
+ collapsed: true,
+ items: [externalGrid]
+ });
+
+ /*
+ * OTA modules
+ */
+
+ var otaSelectionModel = new Ext.grid.CheckboxSelectionModel({
+ singleSelect: false,
+ listeners: {
+ 'rowselect': function(s, ri, r) {
+ moduleSelect(r, 1);
+ },
+ 'rowdeselect': function(s, ri, r) {
+ moduleSelect(r, 0);
+ }
+ }
+ });
+
+ var otaColumnModel = new Ext.grid.ColumnModel([otaSelectionModel, {
+ header: 'Module',
+ dataIndex: 'name',
+ width: 200,
+ sortable: false
+ }]);
+
+ var otaGrid = new Ext.grid.EditorGridPanel({
+ store: otaModuleStore,
+ cm: otaColumnModel,
+ sm: otaSelectionModel,
+ width: 600,
+ height: 150,
+ frame: false,
+ viewConfig: {
+ forceFit: true
+ },
+ iconCls: 'icon-grid'
+ });
+
+ var otaPanel = new Ext.form.FieldSet({
+ title: 'Over-the-air Grabbers',
+ width: 700,
+ autoHeight: true,
+ collapsible: true,
+ collapsed: true,
+ items: [otaGrid]
+ });
+
+ /* ****************************************************************
+ * Form
+ * ***************************************************************/
+
+ var saveButton = new Ext.Button({
+ text: "Save configuration",
+ tooltip: 'Save changes made to configuration below',
+ iconCls: 'save',
+ handler: saveChanges
+ });
+
+ var helpButton = new Ext.Button({
+ text: 'Help',
+ handler: function() {
+ new tvheadend.help('EPG Grab Configuration', 'config_epggrab.html');
+ }
+ });
+
+ var confpanel = new Ext.FormPanel({
+ title: 'EPG Grabber',
+ iconCls: 'xml',
+ border: false,
+ bodyStyle: 'padding:15px',
+ labelAlign: 'left',
+ labelWidth: 150,
+ waitMsgTarget: true,
+ reader: confreader,
+ layout: 'form',
+ defaultType: 'textfield',
+ autoHeight: true,
+ items: [simplePanel, internalPanel, otaPanel, externalPanel],
+ tbar: [saveButton, '->', helpButton]
+ });
+
+ /* ****************************************************************
+ * Load/Save
+ * ***************************************************************/
+
+ /* HACK: get display working */
+ externalGrid.on('render', function() {
+ delay = new Ext.util.DelayedTask(function() {
+ rows = [];
+ externalModuleStore.each(function(r) {
+ if (r.get('enabled'))
+ rows.push(r);
+ });
+ externalSelectionModel.selectRecords(rows);
+ });
+ delay.delay(100);
+ });
+ otaGrid.on('render', function() {
+ delay = new Ext.util.DelayedTask(function() {
+ rows = [];
+ otaModuleStore.each(function(r) {
+ if (r.get('enabled'))
+ rows.push(r);
+ });
+ otaSelectionModel.selectRecords(rows);
+ });
+ delay.delay(100);
+ });
+
+ confpanel.on('render', function() {
+
+ /* Hack to get display working */
+ delay = new Ext.util.DelayedTask(function() {
+ simplePanel.doLayout(false);
+ internalPanel.doLayout(false);
+ externalPanel.doLayout(false);
+ otaPanel.doLayout(false);
+ });
+ delay.delay(100);
+
+ confpanel.getForm().load({
+ url: 'epggrab',
+ params: {
+ op: 'loadSettings'
+ },
+ success: function(form, action) {
+ confpanel.enable();
+ }
+ });
+ });
+
+ function saveChanges() {
+ mods = [];
+ moduleStore.each(function(r) {
+ mods.push({
+ id: r.get('id'),
+ enabled: r.get('enabled') ? 1 : 0
+ });
+ });
+ mods = Ext.util.JSON.encode(mods);
+ confpanel.getForm().submit({
+ url: 'epggrab',
+ params: {
+ op: 'saveSettings',
+ external: mods
+ },
+ waitMsg: 'Saving Data...',
+ success: function(form, action) {
+ externalModuleStore.commitChanges();
+ },
+ failure: function(form, action) {
+ Ext.Msg.alert('Save failed', action.result.errormsg);
+ }
+ });
+ }
- /*
- * Simple fields
- */
- var simplePanel = new Ext.form.FieldSet({
- title : 'General Config',
- width : 700,
- autoHeight : true,
- collapsible : true,
- items : [ channelRename, channelRenumber, channelReicon, epgPeriodicSave ]
- });
-
- /*
- * Internal grabber
- */
- var internalPanel = new Ext.form.FieldSet({
- title : 'Internal Grabber',
- width : 700,
- autoHeight : true,
- collapsible : true,
- items : [ interval, internalModule, intervalValue, intervalUnit ]
- });
-
- /* ****************************************************************
- * Advanced Fields
- * ***************************************************************/
-
- /*
- * External modules
- */
- var externalSelectionModel = new Ext.grid.CheckboxSelectionModel({
- singleSelect : false,
- listeners : {
- 'rowselect' : function(s, ri, r) {
- moduleSelect(r, 1);
- },
- 'rowdeselect' : function(s, ri, r) {
- moduleSelect(r, 0);
- }
- }
- });
-
- var externalColumnModel = new Ext.grid.ColumnModel([ externalSelectionModel,
- {
- header : 'Module',
- dataIndex : 'name',
- width : 200,
- sortable : false
- }, {
- header : 'Path',
- dataIndex : 'path',
- width : 300,
- sortable : false
- } ]);
-
- var externalGrid = new Ext.grid.EditorGridPanel({
- store : externalModuleStore,
- cm : externalColumnModel,
- sm : externalSelectionModel,
- width : 600,
- height : 150,
- frame : false,
- viewConfig : {
- forceFit : true
- },
- iconCls : 'icon-grid'
- });
-
- var externalPanel = new Ext.form.FieldSet({
- title : 'External Interfaces',
- width : 700,
- autoHeight : true,
- collapsible : true,
- collapsed : true,
- items : [ externalGrid ]
- });
-
- /*
- * OTA modules
- */
-
- var otaSelectionModel = new Ext.grid.CheckboxSelectionModel({
- singleSelect : false,
- listeners : {
- 'rowselect' : function(s, ri, r) {
- moduleSelect(r, 1);
- },
- 'rowdeselect' : function(s, ri, r) {
- moduleSelect(r, 0);
- }
- }
- });
-
- var otaColumnModel = new Ext.grid.ColumnModel([ otaSelectionModel, {
- header : 'Module',
- dataIndex : 'name',
- width : 200,
- sortable : false
- } ]);
-
- var otaGrid = new Ext.grid.EditorGridPanel({
- store : otaModuleStore,
- cm : otaColumnModel,
- sm : otaSelectionModel,
- width : 600,
- height : 150,
- frame : false,
- viewConfig : {
- forceFit : true
- },
- iconCls : 'icon-grid'
- });
-
- var otaPanel = new Ext.form.FieldSet({
- title : 'Over-the-air Grabbers',
- width : 700,
- autoHeight : true,
- collapsible : true,
- collapsed : true,
- items : [ otaGrid ]
- });
-
- /* ****************************************************************
- * Form
- * ***************************************************************/
-
- var saveButton = new Ext.Button({
- text : "Save configuration",
- tooltip : 'Save changes made to configuration below',
- iconCls : 'save',
- handler : saveChanges
- });
-
- var helpButton = new Ext.Button({
- text : 'Help',
- handler : function() {
- new tvheadend.help('EPG Grab Configuration', 'config_epggrab.html');
- }
- });
-
- var confpanel = new Ext.FormPanel({
- title : 'EPG Grabber',
- iconCls : 'xml',
- border : false,
- bodyStyle : 'padding:15px',
- labelAlign : 'left',
- labelWidth : 150,
- waitMsgTarget : true,
- reader : confreader,
- layout : 'form',
- defaultType : 'textfield',
- autoHeight : true,
- items : [ simplePanel, internalPanel, otaPanel, externalPanel ],
- tbar : [ saveButton, '->', helpButton ]
- });
-
- /* ****************************************************************
- * Load/Save
- * ***************************************************************/
-
- /* HACK: get display working */
- externalGrid.on('render', function() {
- delay = new Ext.util.DelayedTask(function() {
- rows = [];
- externalModuleStore.each(function(r) {
- if (r.get('enabled')) rows.push(r);
- });
- externalSelectionModel.selectRecords(rows);
- });
- delay.delay(100);
- });
- otaGrid.on('render', function() {
- delay = new Ext.util.DelayedTask(function() {
- rows = [];
- otaModuleStore.each(function(r) {
- if (r.get('enabled')) rows.push(r);
- });
- otaSelectionModel.selectRecords(rows);
- });
- delay.delay(100);
- });
-
- confpanel.on('render', function() {
-
- /* Hack to get display working */
- delay = new Ext.util.DelayedTask(function() {
- simplePanel.doLayout(false);
- internalPanel.doLayout(false);
- externalPanel.doLayout(false);
- otaPanel.doLayout(false);
- });
- delay.delay(100);
-
- confpanel.getForm().load({
- url : 'epggrab',
- params : {
- op : 'loadSettings'
- },
- success : function(form, action) {
- confpanel.enable();
- }
- });
- });
-
- function saveChanges() {
- mods = [];
- moduleStore.each(function(r) {
- mods.push({
- id : r.get('id'),
- enabled : r.get('enabled') ? 1 : 0
- });
- });
- mods = Ext.util.JSON.encode(mods);
- confpanel.getForm().submit({
- url : 'epggrab',
- params : {
- op : 'saveSettings',
- external : mods
- },
- waitMsg : 'Saving Data...',
- success : function(form, action) {
- externalModuleStore.commitChanges();
- },
- failure : function(form, action) {
- Ext.Msg.alert('Save failed', action.result.errormsg);
- }
- });
- }
-
- return confpanel;
-}
+ return confpanel;
+};
tvheadend.esfilter_tab = function(panel)
{
- tvheadend.idnode_grid(panel, {
- url : 'api/esfilter/video',
- comet : 'esfilter_video',
- titleS : 'Video Stream Filter',
- titleP : 'Video Stream Filters',
- tabIndex : 0,
- add : {
- url : 'api/esfilter/video',
- create : {}
- },
- del : true,
- move : true,
- help : function() {
- new tvheadend.help('Elementary Stream Filter', 'config_esfilter.html');
- }
- });
+ tvheadend.idnode_grid(panel, {
+ url: 'api/esfilter/video',
+ comet: 'esfilter_video',
+ titleS: 'Video Stream Filter',
+ titleP: 'Video Stream Filters',
+ tabIndex: 0,
+ add: {
+ url: 'api/esfilter/video',
+ create: {}
+ },
+ del: true,
+ move: true,
+ help: function() {
+ new tvheadend.help('Elementary Stream Filter', 'config_esfilter.html');
+ }
+ });
- tvheadend.idnode_grid(panel, {
- url : 'api/esfilter/audio',
- comet : 'esfilter_audio',
- titleS : 'Audio Stream Filter',
- titleP : 'Audio Stream Filters',
- tabIndex : 1,
- add : {
- url : 'api/esfilter/audio',
- create : {}
- },
- del : true,
- move : true,
- help : function() {
- new tvheadend.help('Elementary Stream Filter', 'config_esfilter.html');
- }
- });
+ tvheadend.idnode_grid(panel, {
+ url: 'api/esfilter/audio',
+ comet: 'esfilter_audio',
+ titleS: 'Audio Stream Filter',
+ titleP: 'Audio Stream Filters',
+ tabIndex: 1,
+ add: {
+ url: 'api/esfilter/audio',
+ create: {}
+ },
+ del: true,
+ move: true,
+ help: function() {
+ new tvheadend.help('Elementary Stream Filter', 'config_esfilter.html');
+ }
+ });
- tvheadend.idnode_grid(panel, {
- url : 'api/esfilter/teletext',
- comet : 'esfilter_teletext',
- titleS : 'Teletext Stream Filter',
- titleP : 'Teletext Stream Filters',
- tabIndex : 2,
- add : {
- url : 'api/esfilter/teletext',
- create : {}
- },
- del : true,
- move : true,
- help : function() {
- new tvheadend.help('Elementary Stream Filter', 'config_esfilter.html');
- }
- });
+ tvheadend.idnode_grid(panel, {
+ url: 'api/esfilter/teletext',
+ comet: 'esfilter_teletext',
+ titleS: 'Teletext Stream Filter',
+ titleP: 'Teletext Stream Filters',
+ tabIndex: 2,
+ add: {
+ url: 'api/esfilter/teletext',
+ create: {}
+ },
+ del: true,
+ move: true,
+ help: function() {
+ new tvheadend.help('Elementary Stream Filter', 'config_esfilter.html');
+ }
+ });
- tvheadend.idnode_grid(panel, {
- url : 'api/esfilter/subtit',
- comet : 'esfilter_subtit',
- titleS : 'Subtitle Stream Filter',
- titleP : 'Subtitle Stream Filters',
- tabIndex : 3,
- add : {
- url : 'api/esfilter/subtit',
- create : {}
- },
- del : true,
- move : true,
- help : function() {
- new tvheadend.help('Elementary Stream Filter', 'config_esfilter.html');
- }
- });
+ tvheadend.idnode_grid(panel, {
+ url: 'api/esfilter/subtit',
+ comet: 'esfilter_subtit',
+ titleS: 'Subtitle Stream Filter',
+ titleP: 'Subtitle Stream Filters',
+ tabIndex: 3,
+ add: {
+ url: 'api/esfilter/subtit',
+ create: {}
+ },
+ del: true,
+ move: true,
+ help: function() {
+ new tvheadend.help('Elementary Stream Filter', 'config_esfilter.html');
+ }
+ });
- tvheadend.idnode_grid(panel, {
- url : 'api/esfilter/ca',
- comet : 'esfilter_ca',
- titleS : 'CA Stream Filter',
- titleP : 'CA Stream Filters',
- tabIndex : 4,
- add : {
- url : 'api/esfilter/ca',
- create : {}
- },
- del : true,
- move : true,
- help : function() {
- new tvheadend.help('Elementary Stream Filter', 'config_esfilter.html');
- }
- });
+ tvheadend.idnode_grid(panel, {
+ url: 'api/esfilter/ca',
+ comet: 'esfilter_ca',
+ titleS: 'CA Stream Filter',
+ titleP: 'CA Stream Filters',
+ tabIndex: 4,
+ add: {
+ url: 'api/esfilter/ca',
+ create: {}
+ },
+ del: true,
+ move: true,
+ help: function() {
+ new tvheadend.help('Elementary Stream Filter', 'config_esfilter.html');
+ }
+ });
- tvheadend.idnode_grid(panel, {
- url : 'api/esfilter/other',
- comet : 'esfilter_other',
- titleS : 'Other Stream Filter',
- titleP : 'Other Stream Filters',
- tabIndex : 5,
- add : {
- url : 'api/esfilter/other',
- create : {}
- },
- del : true,
- move : true,
- help : function() {
- new tvheadend.help('Elementary Stream Filter', 'config_esfilter.html');
- }
- });
-}
+ tvheadend.idnode_grid(panel, {
+ url: 'api/esfilter/other',
+ comet: 'esfilter_other',
+ titleS: 'Other Stream Filter',
+ titleP: 'Other Stream Filters',
+ tabIndex: 5,
+ add: {
+ url: 'api/esfilter/other',
+ create: {}
+ },
+ del: true,
+ move: true,
+ help: function() {
+ new tvheadend.help('Elementary Stream Filter', 'config_esfilter.html');
+ }
+ });
+};
* http://extjs.com/license
*/
#header {
- font-family: tahoma,arial;
+ font-family: tahoma,arial;
background-color: #507AAA;
color: #F8F8F8;
height: 5.3em;
background: url("../img/bg-header.png") repeat-x scroll 0 0 transparent;
height: 45px;
}
-
- #header > h1 {
+
+#header > h1 {
background: url("../img/logo.png") no-repeat scroll 10px 20% transparent;
color: #E0E0E0;
font-size: 22px;
}
.x-tree-col {
- float: left;
- overflow: hidden;
- padding: 0 1px;
- zoom: 1;
+ float: left;
+ overflow: hidden;
+ padding: 0 1px;
+ zoom: 1;
}
.x-tree-col-text,.x-tree-hd-text {
- overflow: hidden;
- -o-text-overflow: ellipsis;
- text-overflow: ellipsis;
- padding: 3px 3px 3px 5px;
- white-space: nowrap;
- font: normal 11px arial, tahoma, helvetica, sans-serif;
+ overflow: hidden;
+ -o-text-overflow: ellipsis;
+ text-overflow: ellipsis;
+ padding: 3px 3px 3px 5px;
+ white-space: nowrap;
+ font: normal 11px arial, tahoma, helvetica, sans-serif;
}
.x-tree-headers {
- background: #f9f9f9
- url(../extjs/resources/images/default/grid/grid3-hrow.gif) repeat-x 0
- bottom;
- cursor: default;
- zoom: 1;
+ background: #f9f9f9
+ url(../extjs/resources/images/default/grid/grid3-hrow.gif) repeat-x 0
+ bottom;
+ cursor: default;
+ zoom: 1;
}
.x-tree-hd {
- float: left;
- overflow: hidden;
- border-left: 1px solid #eee;
- border-right: 1px solid #d0d0d0;
+ float: left;
+ overflow: hidden;
+ border-left: 1px solid #eee;
+ border-right: 1px solid #d0d0d0;
}
.ux-mselect {
- overflow: auto;
- background: white;
- position: relative; /* for calculating scroll offsets */
- zoom: 1;
- overflow: auto;
+ overflow: auto;
+ background: white;
+ position: relative; /* for calculating scroll offsets */
+ zoom: 1;
+ overflow: auto;
}
.ux-mselect-item {
- font: normal 12px tahoma, arial, helvetica, sans-serif;
- padding: 2px;
- border: 1px solid #fff;
- white-space: nowrap;
- cursor: pointer;
+ font: normal 12px tahoma, arial, helvetica, sans-serif;
+ padding: 2px;
+ border: 1px solid #fff;
+ white-space: nowrap;
+ cursor: pointer;
}
.ux-mselect-selected {
- border: 1px dotted #a3bae9 !important;
- background: #DFE8F6;
- cursor: pointer;
+ border: 1px dotted #a3bae9 !important;
+ background: #DFE8F6;
+ cursor: pointer;
}
.x-view-drag-insert-above {
- border-top: 1px dotted #3366cc;
+ border-top: 1px dotted #3366cc;
}
.x-view-drag-insert-below {
- border-bottom: 1px dotted #3366cc;
+ border-bottom: 1px dotted #3366cc;
}
.x-grid3-progresscol .x-grid3-cell-inner {
- padding: 0px 0px 0px 5px;
+ padding: 0px 0px 0px 5px;
}
.x-grid3-progresscol .x-progress-bar {
- height: 16px;
+ height: 16px;
}
.x-grid3-progresscol .x-progress-inner {
- height: 16px;
+ height: 16px;
}
.x-grid3-progresscol .x-progress-text-front-ie6 {
- padding: 2.5px 5px;
+ padding: 2.5px 5px;
}
.x-grid3-progresscol .x-progress-text-front {
- padding: 2px 5px;
+ padding: 2px 5px;
}
.x-progress-bar-red,.x-progress-bar-orange,.x-progress-bar-green {
- border-bottom: 1px solid #7fa9e4;
- float: left;
- height: 16px;
+ border-bottom: 1px solid #7fa9e4;
+ float: left;
+ height: 16px;
}
.x-progress-bar-red {
- background: #ff0000 url(../icons/progress-bg-red.gif) repeat-x scroll
- left center;
- border-top: 1px solid #ecb7ad;
+ background: #ff0000 url(../icons/progress-bg-red.gif) repeat-x scroll
+ left center;
+ border-top: 1px solid #ecb7ad;
}
.x-progress-bar-orange {
- background: #9cbfee url(../icons/progress-bg-orange.gif) repeat-x scroll
- left center;
- border-right: 1px solid #deab7e;
- border-top: 1px solid #d7b290;
+ background: #9cbfee url(../icons/progress-bg-orange.gif) repeat-x scroll
+ left center;
+ border-right: 1px solid #deab7e;
+ border-top: 1px solid #d7b290;
}
.x-progress-bar-green {
- background: #00ff00 url(../icons/progress-bg-green.gif) repeat-x scroll
- left center;
- border-right: 1px solid #5bd976;
- border-top: 1px solid #79e18f;
+ background: #00ff00 url(../icons/progress-bg-green.gif) repeat-x scroll
+ left center;
+ border-right: 1px solid #5bd976;
+ border-top: 1px solid #79e18f;
}
.tvh-grid-unset {
- color: #888;
- font-style: italic;
+ color: #888;
+ font-style: italic;
}
.add {
- background-image: url(../icons/add.png) !important;
+ background-image: url(../icons/add.png) !important;
}
.option {
- background-image: url(../icons/plugin.png) !important;
+ background-image: url(../icons/plugin.png) !important;
}
.remove {
- background-image: url(../icons/delete.png) !important;
+ background-image: url(../icons/delete.png) !important;
}
.moveup {
- background-image: url(../icons/arrow_up.png) !important;
+ background-image: url(../icons/arrow_up.png) !important;
}
.movedown {
- background-image: url(../icons/arrow_down.png) !important;
+ background-image: url(../icons/arrow_down.png) !important;
}
.save {
- background-image: url(../icons/save.png) !important;
+ background-image: url(../icons/save.png) !important;
}
.rec {
- background-image: url(../icons/rec.png) !important;
+ background-image: url(../icons/rec.png) !important;
}
.info {
- background-image: url(../icons/information.png) !important;
+ background-image: url(../icons/information.png) !important;
}
.undo {
- background-image: url(../icons/undo.png) !important;
+ background-image: url(../icons/undo.png) !important;
}
.edit {
- background-image: url(../icons/edit.png) !important;
+ background-image: url(../icons/edit.png) !important;
}
.key {
- background-image: url(../icons/key.png) !important;
+ background-image: url(../icons/key.png) !important;
}
.tags {
- background-image: url(../icons/tag_blue.png) !important;
+ background-image: url(../icons/tag_blue.png) !important;
}
.xml {
- background-image: url(../icons/tag.png) !important;
+ background-image: url(../icons/tag.png) !important;
}
.drive {
- background-image: url(../icons/drive.png) !important;
+ background-image: url(../icons/drive.png) !important;
}
.group {
- background-image: url(../icons/group.png) !important;
+ background-image: url(../icons/group.png) !important;
}
.hardware {
- background-image: url(../icons/pci.png) !important;
+ background-image: url(../icons/pci.png) !important;
}
.television {
- background-image: url(../icons/television.png) !important;
+ background-image: url(../icons/television.png) !important;
}
.eye {
- background-image: url(../icons/eye.png) !important;
+ background-image: url(../icons/eye.png) !important;
}
.control_play {
- background-image: url(../icons/control_play.png) !important;
+ background-image: url(../icons/control_play.png) !important;
}
.control_pause {
- background-image: url(../icons/control_pause.png) !important;
+ background-image: url(../icons/control_pause.png) !important;
}
.control_stop {
- background-image: url(../icons/control_stop.png) !important;
+ background-image: url(../icons/control_stop.png) !important;
}
.control_volume {
- background-image: url(../icons/sound.png) !important;
+ background-image: url(../icons/sound.png) !important;
}
.control_fullscreen {
- background-image: url(../icons/arrow_out.png) !important;
+ background-image: url(../icons/arrow_out.png) !important;
}
.newspaper {
- background-image: url(../icons/newspaper.png) !important;
+ background-image: url(../icons/newspaper.png) !important;
}
.clock {
- background-image: url(../icons/clock.png) !important;
+ background-image: url(../icons/clock.png) !important;
}
.exclamation {
- background-image: url(../icons/exclamation.png) !important;
+ background-image: url(../icons/exclamation.png) !important;
}
.wrench {
- background-image: url(../icons/wrench.png) !important;
+ background-image: url(../icons/wrench.png) !important;
}
.wand {
- background-image: url(../icons/wand.png) !important;
+ background-image: url(../icons/wand.png) !important;
}
.merge {
- background-image: url(../icons/arrow_join.png) !important;
+ background-image: url(../icons/arrow_join.png) !important;
}
.iptv {
- background-image: url(../icons/world.png) !important;
+ background-image: url(../icons/world.png) !important;
}
.clone {
- background-image: url(../icons/layers.png) !important;
+ background-image: url(../icons/layers.png) !important;
}
.scheduled {
- background-image: url(../icons/clock.png) !important;
+ background-image: url(../icons/clock.png) !important;
}
.recordingError {
- background-image: url(../icons/exclamation.png) !important;
+ background-image: url(../icons/exclamation.png) !important;
}
.completed {
- background-image: url(../icons/tick.png) !important;
+ background-image: url(../icons/tick.png) !important;
}
.completedError {
- background-image: url(../icons/exclamation.png) !important;
+ background-image: url(../icons/exclamation.png) !important;
}
.recording {
- background-image: url(../icons/rec.png) !important;
+ background-image: url(../icons/rec.png) !important;
}
.bullet_add {
- background-image: url(../icons/bullet_add.png) !important;
+ background-image: url(../icons/bullet_add.png) !important;
}
.arrow_up {
- background-image: url(../icons/arrow_up.png) !important;
+ background-image: url(../icons/arrow_up.png) !important;
}
.arrow_down {
- background-image: url(../icons/arrow_down.png) !important;
+ background-image: url(../icons/arrow_down.png) !important;
}
.arrow_switch {
- background-image: url(../icons/arrow_switch.png) !important;
+ background-image: url(../icons/arrow_switch.png) !important;
}
.stream_config {
- background-image: url(../icons/film_edit.png) !important;
+ background-image: url(../icons/film_edit.png) !important;
}
.x-smallhdr {
- float: left;
- width: 100px;
+ float: left;
+ width: 100px;
}
.x-epg-title {
- margin: 5px;
- font: normal 15px arial, tahoma, helvetica, sans-serif;
- font-weight: bold;
+ margin: 5px;
+ font: normal 15px arial, tahoma, helvetica, sans-serif;
+ font-weight: bold;
}
.x-epg-subtitle {
- margin: 5px;
- font: normal 12px arial, tahoma, helvetica, sans-serif;
- font-weight: bold;
+ margin: 5px;
+ font: normal 12px arial, tahoma, helvetica, sans-serif;
+ font-weight: bold;
}
.x-epg-desc {
- margin: 5px;
+ margin: 5px;
}
.x-epg-chicon {
- float: right;
- margin: 5px;
- max-width: 132px;
- max-height: 99px;
+ float: right;
+ margin: 5px;
+ max-width: 132px;
+ max-height: 99px;
}
.x-epg-meta {
- margin: 5px;
+ margin: 5px;
}
.hts-t-info {
- float: left;
- width: 100px;
+ float: left;
+ width: 100px;
}
.hts-doc-text {
- font: normal 11px verdana;
- padding: 5px;
+ font: normal 11px verdana;
+ padding: 5px;
}
.hts-doc-text dt {
- padding-top: 10px;
- font-weight: bold;
+ padding-top: 10px;
+ font-weight: bold;
}
.hts-doc-text dl {
- padding-left: 10px;
- padding-bottom: 10px;
+ padding-left: 10px;
+ padding-bottom: 10px;
}
.hts-doc-text li {
- padding-top: 5px;
- padding-bottom: 5px;
+ padding-top: 5px;
+ padding-bottom: 5px;
}
.hts-doc-text img {
- padding: 10px;
+ padding: 10px;
}
.tv-video-player {
}
.about-title {
- font-size: 24px;
- font-weight: bold;
+ font-size: 24px;
+ font-weight: bold;
}
/** vim: ts=4:sw=4:nu:fdc=4:nospell
/* styles for rows */
.ux-row-action-cell .x-grid3-cell-inner {
- padding: 1px 0 0 0;
+ padding: 1px 0 0 0;
}
.ux-row-action-item {
- float: left;
- min-width: 16px;
- height: 16px;
- background-repeat: no-repeat;
- margin: 0 5px 0 0;
- cursor: pointer;
- overflow: hidden;
+ float: left;
+ min-width: 16px;
+ height: 16px;
+ background-repeat: no-repeat;
+ margin: 0 5px 0 0;
+ cursor: pointer;
+ overflow: hidden;
}
.ext-ie .ux-row-action-item {
- width: 16px;
+ width: 16px;
}
.ext-ie .ux-row-action-text {
- width: auto;
+ width: auto;
}
.ux-row-action-item span {
- vertical-align: middle;
- padding: 0 0 0 20px;
- line-height: 18px;
+ vertical-align: middle;
+ padding: 0 0 0 20px;
+ line-height: 18px;
}
.ext-ie .ux-row-action-item span {
- width: auto;
+ width: auto;
}
/* styles for groups */
.x-grid-group-hd div {
- position: relative;
- height: 16px;
+ position: relative;
+ height: 16px;
}
.ux-grow-action-item {
- min-width: 16px;
- height: 16px;
- background-repeat: no-repeat;
- background-position: 0 50% ! important;
- margin: 0 0 0 4px;
- padding: 0 ! important;
- cursor: pointer;
- float: left;
+ min-width: 16px;
+ height: 16px;
+ background-repeat: no-repeat;
+ background-position: 0 50% ! important;
+ margin: 0 0 0 4px;
+ padding: 0 ! important;
+ cursor: pointer;
+ float: left;
}
.ext-ie .ux-grow-action-item {
- width: 16px;
+ width: 16px;
}
.ux-action-right {
- float: right;
- margin: 0 3px 0 2px;
- padding: 0 ! important;
+ float: right;
+ margin: 0 3px 0 2px;
+ padding: 0 ! important;
}
.ux-grow-action-text {
- padding: 0 ! important;
- margin: 0 ! important;
- background: transparent none ! important;
- float: left;
+ padding: 0 ! important;
+ margin: 0 ! important;
+ background: transparent none ! important;
+ float: left;
}
/** vim: ts=4:sw=4:nu:fdc=4:nospell
* License details: http://www.gnu.org/licenses/lgpl.html
*/
.ux-lovcombo-icon {
- width: 16px;
- height: 16px;
- float: left;
- background-position: -1px -1px ! important;
- background-repeat: no-repeat ! important;
+ width: 16px;
+ height: 16px;
+ float: left;
+ background-position: -1px -1px ! important;
+ background-repeat: no-repeat ! important;
}
.ux-lovcombo-icon-checked {
- background: transparent
- url(../extjs/resources/images/default/menu/checked.gif);
+ background: transparent
+ url(../extjs/resources/images/default/menu/checked.gif);
}
.ux-lovcombo-icon-unchecked {
- background: transparent
- url(../extjs/resources/images/default/menu/unchecked.gif);
+ background: transparent
+ url(../extjs/resources/images/default/menu/unchecked.gif);
}
/* eof */
-/*\r
- * Ext JS Library 2.2\r
- * Copyright(c) 2006-2008, Ext JS, LLC.\r
- * licensing@extjs.com\r
- * \r
- * http://extjs.com/license\r
- */\r
-\r
+/*
+ * Ext JS Library 2.2
+ * Copyright(c) 2006-2008, Ext JS, LLC.
+ * licensing@extjs.com
+ *
+ * http://extjs.com/license
+ */
+
/*
* Note that this control should still be treated as an example and that the API will most likely
* change once it is ported into the Ext core as a standard form control. This is still planned
* for a future release, so this should not yet be treated as a final, stable API at this time.
*/
-
+
/**
* @class Ext.ux.MultiSelect
* @extends Ext.form.Field
* Create a new MultiSelect
* @param {Object} config Configuration options
*/
-Ext.ux.Multiselect = Ext.extend(Ext.form.Field, {
+Ext.ux.Multiselect = Ext.extend(Ext.form.Field, {
/**
* @cfg {String} legend Wraps the object with a fieldset and specified legend.
*/
*/
/**
* @cfg {String/Array} dragGroup The ddgroup name(s) for the DDView's DragZone (defaults to undefined).
- */
+ */
/**
* @cfg {String/Array} dropGroup The ddgroup name(s) for the DDView's DropZone (defaults to undefined).
- */
+ */
/**
* @cfg {Object/Array} tbar The top toolbar of the control. This can be a {@link Ext.Toolbar} object, a
* toolbar config, or an array of buttons/button configs to be added to the toolbar.
* @cfg {String} appendOnly True if the list should only allow append drops when drag/drop is enabled
* (use for lists which are sorted, defaults to false).
*/
- appendOnly:false,
+ appendOnly: false,
/**
* @cfg {Array} dataFields Inline data definition when not using a pre-initialised store. Known to cause problems
* in some browswers for very long lists. Use store for large datasets.
*/
- dataFields:[],
+ dataFields: [],
/**
* @cfg {Array} data Inline data when not using a pre-initialised store. Known to cause problems in some
* browswers for very long lists. Use store for large datasets.
*/
- data:[],
+ data: [],
/**
* @cfg {Number} width Width in pixels of the control (defaults to 100).
*/
- width:100,
+ width: 100,
/**
* @cfg {Number} height Height in pixels of the control (defaults to 100).
*/
- height:100,
+ height: 100,
/**
* @cfg {String/Number} displayField Name/Index of the desired display field in the dataset (defaults to 0).
*/
- displayField:0,
+ displayField: 0,
/**
* @cfg {String/Number} valueField Name/Index of the desired value field in the dataset (defaults to 1).
*/
- valueField:1,
+ valueField: 1,
/**
* @cfg {Boolean} allowBlank True to require at least one item in the list to be selected, false to allow no
* selection (defaults to true).
*/
- allowBlank:true,
+ allowBlank: true,
/**
* @cfg {Number} minLength Minimum number of selections allowed (defaults to 0).
*/
- minLength:0,
+ minLength: 0,
/**
* @cfg {Number} maxLength Maximum number of selections allowed (defaults to Number.MAX_VALUE).
*/
- maxLength:Number.MAX_VALUE,
+ maxLength: Number.MAX_VALUE,
/**
* @cfg {String} blankText Default text displayed when the control contains no items (defaults to the same value as
* {@link Ext.form.TextField#blankText}.
*/
- blankText:Ext.form.TextField.prototype.blankText,
+ blankText: Ext.form.TextField.prototype.blankText,
/**
* @cfg {String} minLengthText Validation message displayed when {@link #minLength} is not met (defaults to 'Minimum {0}
* item(s) required'). The {0} token will be replaced by the value of {@link #minLength}.
*/
- minLengthText:'Minimum {0} item(s) required',
+ minLengthText: 'Minimum {0} item(s) required',
/**
* @cfg {String} maxLengthText Validation message displayed when {@link #maxLength} is not met (defaults to 'Maximum {0}
* item(s) allowed'). The {0} token will be replaced by the value of {@link #maxLength}.
*/
- maxLengthText:'Maximum {0} item(s) allowed',
+ maxLengthText: 'Maximum {0} item(s) allowed',
/**
* @cfg {String} delimiter The string used to delimit between items when set or returned as a string of values
* (defaults to ',').
*/
- delimiter:',',
-
+ delimiter: ',',
// DDView settings
- copy:false,
- allowDup:false,
- allowTrash:false,
- focusClass:undefined,
- sortDir:'ASC',
-
+ copy: false,
+ allowDup: false,
+ allowTrash: false,
+ focusClass: undefined,
+ sortDir: 'ASC',
// private
- defaultAutoCreate : {tag: "div"},
-
+ defaultAutoCreate: {tag: "div"},
// private
- initComponent: function(){
+ initComponent: function() {
Ext.ux.Multiselect.superclass.initComponent.call(this);
this.addEvents({
- 'dblclick' : true,
- 'click' : true,
- 'change' : true,
- 'drop' : true
- });
+ 'dblclick': true,
+ 'click': true,
+ 'change': true,
+ 'drop': true
+ });
},
-
// private
- onRender: function(ct, position){
+ onRender: function(ct, position) {
Ext.ux.Multiselect.superclass.onRender.call(this, ct, position);
-
+
var cls = 'ux-mselect';
var fs = new Ext.form.FieldSet({
- renderTo:this.el,
- title:this.legend,
- height:this.height,
- width:this.width,
- style:"padding:0;",
- tbar:this.tbar
+ renderTo: this.el,
+ title: this.legend,
+ height: this.height,
+ width: this.width,
+ style: "padding:0;",
+ tbar: this.tbar
});
//if(!this.legend)fs.el.down('.'+fs.headerCls).remove();
fs.body.addClass(cls);
var tpl = '<tpl for="."><div class="' + cls + '-item';
- if(Ext.isIE || Ext.isIE7){
- tpl+='" unselectable=on';
- }else{
- tpl+=' x-unselectable"';
+ if (Ext.isIE || Ext.isIE7) {
+ tpl += '" unselectable=on';
+ } else {
+ tpl += ' x-unselectable"';
}
- tpl+='>{' + this.displayField + '}</div></tpl>';
+ tpl += '>{' + this.displayField + '}</div></tpl>';
- if(!this.store){
+ if (!this.store) {
this.store = new Ext.data.SimpleStore({
fields: this.dataFields,
- data : this.data
+ data: this.data
});
}
this.view = new Ext.ux.DDView({
- multiSelect: true,
- store: this.store,
- selectedClass: cls+"-selected",
- tpl:tpl,
- allowDup:this.allowDup,
- copy: this.copy,
- allowTrash: this.allowTrash,
- dragGroup: this.dragGroup,
- dropGroup: this.dropGroup,
- itemSelector:"."+cls+"-item",
- isFormField:false,
- applyTo:fs.body,
- appendOnly:this.appendOnly,
- sortField:this.sortField,
- sortDir:this.sortDir
+ multiSelect: true,
+ store: this.store,
+ selectedClass: cls + "-selected",
+ tpl: tpl,
+ allowDup: this.allowDup,
+ copy: this.copy,
+ allowTrash: this.allowTrash,
+ dragGroup: this.dragGroup,
+ dropGroup: this.dropGroup,
+ itemSelector: "." + cls + "-item",
+ isFormField: false,
+ applyTo: fs.body,
+ appendOnly: this.appendOnly,
+ sortField: this.sortField,
+ sortDir: this.sortDir
});
fs.add(this.view);
-
+
this.view.on('click', this.onViewClick, this);
this.view.on('beforeClick', this.onViewBeforeClick, this);
this.view.on('dblclick', this.onViewDblClick, this);
- this.view.on('drop', function(ddView, n, dd, e, data){
+ this.view.on('drop', function(ddView, n, dd, e, data) {
return this.fireEvent("drop", ddView, n, dd, e, data);
}, this);
-
+
this.hiddenName = this.name;
- var hiddenTag={tag: "input", type: "hidden", value: "", name:this.name};
- if (this.isFormField) {
+ var hiddenTag = {tag: "input", type: "hidden", value: "", name: this.name};
+ if (this.isFormField) {
this.hiddenField = this.el.createChild(hiddenTag);
} else {
this.hiddenField = Ext.get(document.body).createChild(hiddenTag);
}
fs.doLayout();
},
-
// private
- initValue:Ext.emptyFn,
-
+ initValue: Ext.emptyFn,
// private
onViewClick: function(vw, index, node, e) {
var arrayIndex = this.preClickSelections.indexOf(index);
- if (arrayIndex != -1)
+ if (arrayIndex !== -1)
{
this.preClickSelections.splice(arrayIndex, 1);
this.view.clearSelections(true);
this.fireEvent('change', this, this.getValue(), this.hiddenField.dom.value);
this.hiddenField.dom.value = this.getValue();
this.fireEvent('click', this, e);
- this.validate();
+ this.validate();
},
-
// private
onViewBeforeClick: function(vw, index, node, e) {
this.preClickSelections = this.view.getSelectedIndexes();
- if (this.disabled) {return false;}
+ if (this.disabled) {
+ return false;
+ }
},
-
// private
- onViewDblClick : function(vw, index, node, e) {
- return this.fireEvent('dblclick', vw, index, node, e);
- },
-
+ onViewDblClick: function(vw, index, node, e) {
+ return this.fireEvent('dblclick', vw, index, node, e); },
/**
* Returns an array of data values for the selected items in the list. The values will be separated
* by {@link #delimiter}.
* @return {Array} value An array of string data values
*/
- getValue: function(valueField){
+ getValue: function(valueField) {
var returnArray = [];
var selectionsArray = this.view.getSelectedIndexes();
- if (selectionsArray.length == 0) {return '';}
- for (var i=0; i<selectionsArray.length; i++) {
- returnArray.push(this.store.getAt(selectionsArray[i]).get(((valueField != null)? valueField : this.valueField)));
+ if (selectionsArray.length === 0) {
+ return '';
+ }
+ for (var i = 0; i < selectionsArray.length; i++) {
+ returnArray.push(this.store.getAt(selectionsArray[i]).get(((valueField != null) ? valueField : this.valueField)));
}
return returnArray.join(this.delimiter);
},
-
/**
* Sets a delimited string (using {@link #delimiter}) or array of data values into the list.
* @param {String/Array} values The values to set
var selections = [];
this.view.clearSelections();
this.hiddenField.dom.value = '';
-
- if (!values || (values == '')) { return; }
-
- if (!(values instanceof Array)) { values = values.split(this.delimiter); }
- for (var i=0; i<values.length; i++) {
- index = this.view.store.indexOf(this.view.store.query(this.valueField,
- new RegExp('^' + values[i] + '$', "i")).itemAt(0));
+
+ if (!values || (values === '')) {
+ return;
+ }
+
+ if (!(values instanceof Array)) {
+ values = values.split(this.delimiter);
+ }
+ for (var i = 0; i < values.length; i++) {
+ index = this.view.store.indexOf(this.view.store.query(this.valueField,
+ new RegExp('^' + values[i] + '$', "i")).itemAt(0));
selections.push(index);
}
this.view.select(selections);
this.hiddenField.dom.value = this.getValue();
this.validate();
},
-
// inherit docs
- reset : function() {
+ reset: function() {
this.setValue('');
},
-
// inherit docs
getRawValue: function(valueField) {
var tmp = this.getValue(valueField);
if (tmp.length) {
tmp = tmp.split(this.delimiter);
}
- else{
+ else {
tmp = [];
}
return tmp;
},
-
// inherit docs
- setRawValue: function(values){
+ setRawValue: function(values) {
setValue(values);
},
-
// inherit docs
- validateValue : function(value){
+ validateValue: function(value) {
if (value.length < 1) { // if it has no value
- if (this.allowBlank) {
- this.clearInvalid();
- return true;
- } else {
- this.markInvalid(this.blankText);
- return false;
- }
+ if (this.allowBlank) {
+ this.clearInvalid();
+ return true;
+ } else {
+ this.markInvalid(this.blankText);
+ return false;
+ }
}
if (value.length < this.minLength) {
this.markInvalid(String.format(this.minLengthText, this.minLength));
Ext.namespace('Ext.ux.grid');
Ext.ux.grid.ProgressColumn = function(config) {
- Ext.apply(this, config);
- this.renderer = this.renderer.createDelegate(this);
- this.addEvents('action');
- Ext.ux.grid.ProgressColumn.superclass.constructor.call(this);
+ Ext.apply(this, config);
+ this.renderer = this.renderer.createDelegate(this);
+ this.addEvents('action');
+ Ext.ux.grid.ProgressColumn.superclass.constructor.call(this);
};
Ext.extend(Ext.ux.grid.ProgressColumn, Ext.util.Observable, {
- /**
- * @cfg {String} colored determines whether use special progression coloring
- * or the standard Ext.ProgressBar coloring for the bar (defaults to
- * false)
- */
- textPst : '%',
- /**
- * @cfg {String} colored determines whether use special progression coloring
- * or the standard Ext.ProgressBar coloring for the bar (defaults to
- * false)
- */
- colored : false,
- /**
- * @cfg {String} actionEvent Event to trigger actions, e.g. click, dblclick,
- * mouseover (defaults to 'dblclick')
- */
- actionEvent : 'dblclick',
-
- init : function(grid) {
- this.grid = grid;
- this.view = grid.getView();
-
- if (this.editor && grid.isEditor) {
- var cfg = {
- scope : this
- };
- cfg[this.actionEvent] = this.onClick;
- grid.afterRender = grid.afterRender.createSequence(function() {
- this.view.mainBody.on(cfg);
- }, this);
- }
- },
+ /**
+ * @cfg {String} colored determines whether use special progression coloring
+ * or the standard Ext.ProgressBar coloring for the bar (defaults to
+ * false)
+ */
+ textPst: '%',
+ /**
+ * @cfg {String} colored determines whether use special progression coloring
+ * or the standard Ext.ProgressBar coloring for the bar (defaults to
+ * false)
+ */
+ colored: false,
+ /**
+ * @cfg {String} actionEvent Event to trigger actions, e.g. click, dblclick,
+ * mouseover (defaults to 'dblclick')
+ */
+ actionEvent: 'dblclick',
+ init: function(grid) {
+ this.grid = grid;
+ this.view = grid.getView();
+
+ if (this.editor && grid.isEditor) {
+ var cfg = {
+ scope: this
+ };
+ cfg[this.actionEvent] = this.onClick;
+ grid.afterRender = grid.afterRender.createSequence(function() {
+ this.view.mainBody.on(cfg);
+ }, this);
+ }
+ },
+ onClick: function(e, target) {
+ var rowIndex = e.getTarget('.x-grid3-row').rowIndex;
+ var colIndex = this.view.findCellIndex(target.parentNode.parentNode);
- onClick : function(e, target) {
- var rowIndex = e.getTarget('.x-grid3-row').rowIndex;
- var colIndex = this.view.findCellIndex(target.parentNode.parentNode);
+ var t = e.getTarget('.x-progress-text');
+ if (t) {
+ this.grid.startEditing(rowIndex, colIndex);
+ }
+ },
+ renderer: function(v, p, record) {
+ var style = '';
+ var textClass = (v < 55) ? 'x-progress-text-back' : 'x-progress-text-front' + (Ext.isIE6 ? '-ie6' : '');
+
+ //ugly hack to deal with IE6 issue
+ var text = String.format('</div><div class="x-progress-text {0}" style="width:100%;" id="{1}">{2}</div></div>',
+ textClass, Ext.id(), v + this.textPst
+ );
+ text = (v < 96) ? text.substring(0, text.length - 6) : text.substr(6);
+
+ if (this.colored == true) {
+ if (v <= 100 && v > 66)
+ style = '-green';
+ if (v < 67 && v > 33)
+ style = '-orange';
+ if (v < 34)
+ style = '-red';
+ }
- var t = e.getTarget('.x-progress-text');
- if (t) {
- this.grid.startEditing(rowIndex, colIndex);
- }
- },
-
- renderer : function(v, p, record) {
- var style = '';
- var textClass = (v < 55) ? 'x-progress-text-back' : 'x-progress-text-front' + (Ext.isIE6 ? '-ie6' : '');
-
- //ugly hack to deal with IE6 issue
- var text = String.format('</div><div class="x-progress-text {0}" style="width:100%;" id="{1}">{2}</div></div>',
- textClass, Ext.id(), v + this.textPst
- );
- text = (v<96) ? text.substring(0, text.length - 6) : text.substr(6);
-
- if (this.colored == true) {
- if (v <= 100 && v > 66)
- style = '-green';
- if (v < 67 && v > 33)
- style = '-orange';
- if (v < 34)
- style = '-red';
+ p.css += ' x-grid3-progresscol';
+ return String.format(
+ '<div class="x-progress-wrap"><div class="x-progress-inner"><div class="x-progress-bar{0}" style="width:{1}%;">{2}</div>' +
+ '</div>', style, v, text
+ );
}
-
- p.css += ' x-grid3-progresscol';
- return String.format(
- '<div class="x-progress-wrap"><div class="x-progress-inner"><div class="x-progress-bar{0}" style="width:{1}%;">{2}</div>' +
- '</div>', style, v, text
- );
- }
});
//vim: ts=4:sw=4:nu:fdc=4:nospell
Ext.ns('Ext.ux.grid');
// add RegExp.escape if it has not been already added
-if('function' !== typeof RegExp.escape) {
- RegExp.escape = function(s) {
- if('string' !== typeof s) {
- return s;
- }
- // Note: if pasting from forum, precede ]/\ with backslash manually
- return s.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g, '\\$1');
- }; // eo function escape
+if ('function' !== typeof RegExp.escape) {
+ RegExp.escape = function(s) {
+ if ('string' !== typeof s) {
+ return s;
+ }
+ // Note: if pasting from forum, precede ]/\ with backslash manually
+ return s.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g, '\\$1');
+ }; // eo function escape
}
/**
* @param {Object} config A config object
*/
Ext.ux.grid.RowActions = function(config) {
- Ext.apply(this, config);
-
- // {{{
- this.addEvents(
- /**
- * @event beforeaction
- * Fires before action event. Return false to cancel the subsequent action event.
- * @param {Ext.grid.GridPanel} grid
- * @param {Ext.data.Record} record Record corresponding to row clicked
- * @param {String} action Identifies the action icon clicked. Equals to icon css class name.
- * @param {Integer} rowIndex Index of clicked grid row
- * @param {Integer} colIndex Index of clicked grid column that contains all action icons
- */
- 'beforeaction'
- /**
- * @event action
- * Fires when icon is clicked
- * @param {Ext.grid.GridPanel} grid
- * @param {Ext.data.Record} record Record corresponding to row clicked
- * @param {String} action Identifies the action icon clicked. Equals to icon css class name.
- * @param {Integer} rowIndex Index of clicked grid row
- * @param {Integer} colIndex Index of clicked grid column that contains all action icons
- */
- ,'action'
- /**
- * @event beforegroupaction
- * Fires before group action event. Return false to cancel the subsequent groupaction event.
- * @param {Ext.grid.GridPanel} grid
- * @param {Array} records Array of records in this group
- * @param {String} action Identifies the action icon clicked. Equals to icon css class name.
- * @param {String} groupId Identifies the group clicked
- */
- ,'beforegroupaction'
- /**
- * @event groupaction
- * Fires when icon in a group header is clicked
- * @param {Ext.grid.GridPanel} grid
- * @param {Array} records Array of records in this group
- * @param {String} action Identifies the action icon clicked. Equals to icon css class name.
- * @param {String} groupId Identifies the group clicked
- */
- ,'groupaction'
- );
- // }}}
-
- // call parent
- Ext.ux.grid.RowActions.superclass.constructor.call(this);
+ Ext.apply(this, config);
+
+ // {{{
+ this.addEvents(
+ /**
+ * @event beforeaction
+ * Fires before action event. Return false to cancel the subsequent action event.
+ * @param {Ext.grid.GridPanel} grid
+ * @param {Ext.data.Record} record Record corresponding to row clicked
+ * @param {String} action Identifies the action icon clicked. Equals to icon css class name.
+ * @param {Integer} rowIndex Index of clicked grid row
+ * @param {Integer} colIndex Index of clicked grid column that contains all action icons
+ */
+ 'beforeaction'
+ /**
+ * @event action
+ * Fires when icon is clicked
+ * @param {Ext.grid.GridPanel} grid
+ * @param {Ext.data.Record} record Record corresponding to row clicked
+ * @param {String} action Identifies the action icon clicked. Equals to icon css class name.
+ * @param {Integer} rowIndex Index of clicked grid row
+ * @param {Integer} colIndex Index of clicked grid column that contains all action icons
+ */
+ , 'action'
+ /**
+ * @event beforegroupaction
+ * Fires before group action event. Return false to cancel the subsequent groupaction event.
+ * @param {Ext.grid.GridPanel} grid
+ * @param {Array} records Array of records in this group
+ * @param {String} action Identifies the action icon clicked. Equals to icon css class name.
+ * @param {String} groupId Identifies the group clicked
+ */
+ , 'beforegroupaction'
+ /**
+ * @event groupaction
+ * Fires when icon in a group header is clicked
+ * @param {Ext.grid.GridPanel} grid
+ * @param {Array} records Array of records in this group
+ * @param {String} action Identifies the action icon clicked. Equals to icon css class name.
+ * @param {String} groupId Identifies the group clicked
+ */
+ , 'groupaction'
+ );
+ // }}}
+
+ // call parent
+ Ext.ux.grid.RowActions.superclass.constructor.call(this);
};
Ext.extend(Ext.ux.grid.RowActions, Ext.util.Observable, {
+ // configuration options
+ // {{{
+ /**
+ * @cfg {Array} actions Mandatory. Array of action configuration objects. The action
+ * configuration object recognizes the following options:
+ * <ul class="list">
+ * <li style="list-style-position:outside">
+ * {Function} <b>callback</b> (optional). Function to call if the action icon is clicked.
+ * This function is called with same signature as action event and in its original scope.
+ * If you need to call it in different scope or with another signature use
+ * createCallback or createDelegate functions. Works for statically defined actions. Use
+ * callbacks configuration options for store bound actions.
+ * </li>
+ * <li style="list-style-position:outside">
+ * {Function} <b>cb</b> Shortcut for callback.
+ * </li>
+ * <li style="list-style-position:outside">
+ * {String} <b>iconIndex</b> Optional, however either iconIndex or iconCls must be
+ * configured. Field name of the field of the grid store record that contains
+ * css class of the icon to show. If configured, shown icons can vary depending
+ * of the value of this field.
+ * </li>
+ * <li style="list-style-position:outside">
+ * {String} <b>iconCls</b> CSS class of the icon to show. It is ignored if iconIndex is
+ * configured. Use this if you want static icons that are not base on the values in the record.
+ * </li>
+ * <li style="list-style-position:outside">
+ * {Boolean} <b>hide</b> Optional. True to hide this action while still have a space in
+ * the grid column allocated to it. IMO, it doesn't make too much sense, use hideIndex instead.
+ * </li>
+ * <li style="list-style-position:outside">
+ * {String} <b>hideIndex</b> Optional. Field name of the field of the grid store record that
+ * contains hide flag (falsie [null, '', 0, false, undefined] to show, anything else to hide).
+ * </li>
+ * <li style="list-style-position:outside">
+ * {String} <b>qtipIndex</b> Optional. Field name of the field of the grid store record that
+ * contains tooltip text. If configured, the tooltip texts are taken from the store.
+ * </li>
+ * <li style="list-style-position:outside">
+ * {String} <b>tooltip</b> Optional. Tooltip text to use as icon tooltip. It is ignored if
+ * qtipIndex is configured. Use this if you want static tooltips that are not taken from the store.
+ * </li>
+ * <li style="list-style-position:outside">
+ * {String} <b>qtip</b> Synonym for tooltip
+ * </li>
+ * <li style="list-style-position:outside">
+ * {String} <b>textIndex</b> Optional. Field name of the field of the grids store record
+ * that contains text to display on the right side of the icon. If configured, the text
+ * shown is taken from record.
+ * </li>
+ * <li style="list-style-position:outside">
+ * {String} <b>text</b> Optional. Text to display on the right side of the icon. Use this
+ * if you want static text that are not taken from record. Ignored if textIndex is set.
+ * </li>
+ * <li style="list-style-position:outside">
+ * {String} <b>style</b> Optional. Style to apply to action icon container.
+ * </li>
+ * </ul>
+ */
+
+ /**
+ * @cfg {String} actionEvent Event to trigger actions, e.g. click, dblclick, mouseover (defaults to 'click')
+ */
+ actionEvent: 'click'
+ /**
+ * @cfg {Boolean} autoWidth true to calculate field width for iconic actions only (defaults to true).
+ * If true, the width is calculated as {@link #widthSlope} * number of actions + {@link #widthIntercept}.
+ */
+ , autoWidth: true
+
+ /**
+ * @cfg {String} dataIndex - Do not touch!
+ * @private
+ */
+ , dataIndex: ''
+
+ /**
+ * @cfg {Boolean} editable - Do not touch!
+ * Must be false to prevent errors in editable grids
+ */
+ , editable: false
+
+ /**
+ * @cfg {Array} groupActions Array of action to use for group headers of grouping grids.
+ * These actions support static icons, texts and tooltips same way as {@link #actions}. There is one
+ * more action config option recognized:
+ * <ul class="list">
+ * <li style="list-style-position:outside">
+ * {String} <b>align</b> Set it to 'left' to place action icon next to the group header text.
+ * (defaults to undefined = icons are placed at the right side of the group header.
+ * </li>
+ * </ul>
+ */
+
+ /**
+ * @cfg {Object} callbacks iconCls keyed object that contains callback functions. For example:
+ * <pre>
+ * callbacks:{
+ * 'icon-open':function(...) {...}
+ * ,'icon-save':function(...) {...}
+ * }
+ * </pre>
+ */
+
+ /**
+ * @cfg {String} header Actions column header
+ */
+ , header: ''
+
+ /**
+ * @cfg {Boolean} isColumn
+ * Tell ColumnModel that we are column. Do not touch!
+ * @private
+ */
+ , isColumn: true
+
+ /**
+ * @cfg {Boolean} keepSelection
+ * Set it to true if you do not want action clicks to affect selected row(s) (defaults to false).
+ * By default, when user clicks an action icon the clicked row is selected and the action events are fired.
+ * If this option is true then the current selection is not affected, only the action events are fired.
+ */
+ , keepSelection: false
+
+ /**
+ * @cfg {Boolean} menuDisabled No sense to display header menu for this column
+ * @private
+ */
+ , menuDisabled: true
+
+ /**
+ * @cfg {Boolean} sortable Usually it has no sense to sort by this column
+ * @private
+ */
+ , sortable: false
+
+ /**
+ * @cfg {String} tplGroup Template for group actions
+ * @private
+ */
+ , tplGroup:
+ '<tpl for="actions">'
+ + '<div class="ux-grow-action-item<tpl if="\'right\'===align"> ux-action-right</tpl> '
+ + '{cls}" style="{style}" qtip="{qtip}">{text}</div>'
+ + '</tpl>'
+
+ /**
+ * @cfg {String} tplRow Template for row actions
+ * @private
+ */
+ , tplRow:
+ '<div class="ux-row-action">'
+ + '<tpl for="actions">'
+ + '<div class="ux-row-action-item {cls} <tpl if="text">'
+ + 'ux-row-action-text</tpl>" style="{hide}{style}" qtip="{qtip}">'
+ + '<tpl if="text"><span qtip="{qtip}">{text}</span></tpl></div>'
+ + '</tpl>'
+ + '</div>'
+
+ /**
+ * @cfg {String} hideMode How to hide hidden icons. Valid values are: 'visibility' and 'display'
+ * (defaluts to 'visibility'). If the mode is visibility the hidden icon is not visible but there
+ * is still blank space occupied by the icon. In display mode, the visible icons are shifted taking
+ * the space of the hidden icon.
+ */
+ , hideMode: 'visibility'
+
+ /**
+ * @cfg {Number} widthIntercept Constant used for auto-width calculation (defaults to 4).
+ * See {@link #autoWidth} for explanation.
+ */
+ , widthIntercept: 4
+
+ /**
+ * @cfg {Number} widthSlope Constant used for auto-width calculation (defaults to 21).
+ * See {@link #autoWidth} for explanation.
+ */
+ , widthSlope: 21
+ // }}}
+
+ // methods
+ // {{{
+ /**
+ * Init function
+ * @param {Ext.grid.GridPanel} grid Grid this plugin is in
+ */
+ , init: function(grid) {
+ this.grid = grid;
+
+ // the actions column must have an id for Ext 3.x
+ this.id = this.id || Ext.id();
+
+ // for Ext 3.x compatibility
+ var lookup = grid.getColumnModel().lookup;
+ delete(lookup[undefined]);
+ lookup[this.id] = this;
+
+ // {{{
+ // setup template
+ if (!this.tpl) {
+ this.tpl = this.processActions(this.actions);
+
+ } // eo template setup
+ // }}}
+
+ // calculate width
+ if (this.autoWidth) {
+ this.width = this.widthSlope * this.actions.length + this.widthIntercept;
+ this.fixed = true;
+ }
+
+ // body click handler
+ var view = grid.getView();
+ var cfg = {scope: this};
+ cfg[this.actionEvent] = this.onClick;
+ grid.afterRender = grid.afterRender.createSequence(function() {
+ view.mainBody.on(cfg);
+ grid.on('destroy', this.purgeListeners, this);
+ }, this);
+
+ // setup renderer
+ if (!this.renderer) {
+ this.renderer = function(value, cell, record, row, col, store) {
+ cell.css += (cell.css ? ' ' : '') + 'ux-row-action-cell';
+ return this.tpl.apply(this.getData(value, cell, record, row, col, store));
+ }.createDelegate(this);
+ }
+
+ // actions in grouping grids support
+ if (view.groupTextTpl && this.groupActions) {
+ view.interceptMouse = view.interceptMouse.createInterceptor(function(e) {
+ if (e.getTarget('.ux-grow-action-item')) {
+ return false;
+ }
+ });
+ view.groupTextTpl =
+ '<div class="ux-grow-action-text">' + view.groupTextTpl + '</div>'
+ + this.processActions(this.groupActions, this.tplGroup).apply()
+ ;
+ }
+
+ // cancel click
+ if (true === this.keepSelection) {
+ grid.processEvent = grid.processEvent.createInterceptor(function(name, e) {
+ if ('mousedown' === name) {
+ return !this.getAction(e);
+ }
+ }, this);
+ }
+
+ } // eo function init
+ // }}}
+ // {{{
+ /**
+ * Returns data to apply to template. Override this if needed.
+ * @param {Mixed} value
+ * @param {Object} cell object to set some attributes of the grid cell
+ * @param {Ext.data.Record} record from which the data is extracted
+ * @param {Number} row row index
+ * @param {Number} col col index
+ * @param {Ext.data.Store} store object from which the record is extracted
+ * @return {Object} data to apply to template
+ */
+ , getData: function(value, cell, record, row, col, store) {
+ return record.data || {};
+ } // eo function getData
+ // }}}
+ // {{{
+ /**
+ * Processes actions configs and returns template.
+ * @param {Array} actions
+ * @param {String} template Optional. Template to use for one action item.
+ * @return {String}
+ * @private
+ */
+ , processActions: function(actions, template) {
+ var acts = [];
+
+ // actions loop
+ Ext.each(actions, function(a, i) {
+ // save callback
+ if (a.iconCls && 'function' === typeof (a.callback || a.cb)) {
+ this.callbacks = this.callbacks || {};
+ this.callbacks[a.iconCls] = a.callback || a.cb;
+ }
+
+ // data for intermediate template
+ var o = {
+ cls: a.iconIndex ? '{' + a.iconIndex + '}' : (a.iconCls ? a.iconCls : '')
+ , qtip: a.qtipIndex ? '{' + a.qtipIndex + '}' : (a.tooltip || a.qtip ? a.tooltip || a.qtip : '')
+ , text: a.textIndex ? '{' + a.textIndex + '}' : (a.text ? a.text : '')
+ , hide: a.hideIndex
+ ? '<tpl if="' + a.hideIndex + '">'
+ + ('display' === this.hideMode ? 'display:none' : 'visibility:hidden') + ';</tpl>'
+ : (a.hide ? ('display' === this.hideMode ? 'display:none' : 'visibility:hidden;') : '')
+ , align: a.align || 'right'
+ , style: a.style ? a.style : ''
+ };
+ acts.push(o);
+
+ }, this); // eo actions loop
+
+ var xt = new Ext.XTemplate(template || this.tplRow);
+ return new Ext.XTemplate(xt.apply({actions: acts}));
+
+ } // eo function processActions
+ // }}}
+ , getAction: function(e) {
+ var action = false;
+ var t = e.getTarget('.ux-row-action-item');
+ if (t) {
+ action = t.className.replace(/ux-row-action-item /, '');
+ if (action) {
+ action = action.replace(/ ux-row-action-text/, '');
+ action = action.trim();
+ }
+ }
+ return action;
+ } // eo function getAction
+ // {{{
+ /**
+ * Grid body actionEvent event handler
+ * @private
+ */
+ , onClick: function(e, target) {
+
+ var view = this.grid.getView();
- // configuration options
- // {{{
- /**
- * @cfg {Array} actions Mandatory. Array of action configuration objects. The action
- * configuration object recognizes the following options:
- * <ul class="list">
- * <li style="list-style-position:outside">
- * {Function} <b>callback</b> (optional). Function to call if the action icon is clicked.
- * This function is called with same signature as action event and in its original scope.
- * If you need to call it in different scope or with another signature use
- * createCallback or createDelegate functions. Works for statically defined actions. Use
- * callbacks configuration options for store bound actions.
- * </li>
- * <li style="list-style-position:outside">
- * {Function} <b>cb</b> Shortcut for callback.
- * </li>
- * <li style="list-style-position:outside">
- * {String} <b>iconIndex</b> Optional, however either iconIndex or iconCls must be
- * configured. Field name of the field of the grid store record that contains
- * css class of the icon to show. If configured, shown icons can vary depending
- * of the value of this field.
- * </li>
- * <li style="list-style-position:outside">
- * {String} <b>iconCls</b> CSS class of the icon to show. It is ignored if iconIndex is
- * configured. Use this if you want static icons that are not base on the values in the record.
- * </li>
- * <li style="list-style-position:outside">
- * {Boolean} <b>hide</b> Optional. True to hide this action while still have a space in
- * the grid column allocated to it. IMO, it doesn't make too much sense, use hideIndex instead.
- * </li>
- * <li style="list-style-position:outside">
- * {String} <b>hideIndex</b> Optional. Field name of the field of the grid store record that
- * contains hide flag (falsie [null, '', 0, false, undefined] to show, anything else to hide).
- * </li>
- * <li style="list-style-position:outside">
- * {String} <b>qtipIndex</b> Optional. Field name of the field of the grid store record that
- * contains tooltip text. If configured, the tooltip texts are taken from the store.
- * </li>
- * <li style="list-style-position:outside">
- * {String} <b>tooltip</b> Optional. Tooltip text to use as icon tooltip. It is ignored if
- * qtipIndex is configured. Use this if you want static tooltips that are not taken from the store.
- * </li>
- * <li style="list-style-position:outside">
- * {String} <b>qtip</b> Synonym for tooltip
- * </li>
- * <li style="list-style-position:outside">
- * {String} <b>textIndex</b> Optional. Field name of the field of the grids store record
- * that contains text to display on the right side of the icon. If configured, the text
- * shown is taken from record.
- * </li>
- * <li style="list-style-position:outside">
- * {String} <b>text</b> Optional. Text to display on the right side of the icon. Use this
- * if you want static text that are not taken from record. Ignored if textIndex is set.
- * </li>
- * <li style="list-style-position:outside">
- * {String} <b>style</b> Optional. Style to apply to action icon container.
- * </li>
- * </ul>
- */
-
- /**
- * @cfg {String} actionEvent Event to trigger actions, e.g. click, dblclick, mouseover (defaults to 'click')
- */
- actionEvent:'click'
- /**
- * @cfg {Boolean} autoWidth true to calculate field width for iconic actions only (defaults to true).
- * If true, the width is calculated as {@link #widthSlope} * number of actions + {@link #widthIntercept}.
- */
- ,autoWidth:true
-
- /**
- * @cfg {String} dataIndex - Do not touch!
- * @private
- */
- ,dataIndex:''
-
- /**
- * @cfg {Boolean} editable - Do not touch!
- * Must be false to prevent errors in editable grids
- */
- ,editable:false
-
- /**
- * @cfg {Array} groupActions Array of action to use for group headers of grouping grids.
- * These actions support static icons, texts and tooltips same way as {@link #actions}. There is one
- * more action config option recognized:
- * <ul class="list">
- * <li style="list-style-position:outside">
- * {String} <b>align</b> Set it to 'left' to place action icon next to the group header text.
- * (defaults to undefined = icons are placed at the right side of the group header.
- * </li>
- * </ul>
- */
-
- /**
- * @cfg {Object} callbacks iconCls keyed object that contains callback functions. For example:
- * <pre>
- * callbacks:{
- * 'icon-open':function(...) {...}
- * ,'icon-save':function(...) {...}
- * }
- * </pre>
- */
-
- /**
- * @cfg {String} header Actions column header
- */
- ,header:''
-
- /**
- * @cfg {Boolean} isColumn
- * Tell ColumnModel that we are column. Do not touch!
- * @private
- */
- ,isColumn:true
-
- /**
- * @cfg {Boolean} keepSelection
- * Set it to true if you do not want action clicks to affect selected row(s) (defaults to false).
- * By default, when user clicks an action icon the clicked row is selected and the action events are fired.
- * If this option is true then the current selection is not affected, only the action events are fired.
- */
- ,keepSelection:false
-
- /**
- * @cfg {Boolean} menuDisabled No sense to display header menu for this column
- * @private
- */
- ,menuDisabled:true
-
- /**
- * @cfg {Boolean} sortable Usually it has no sense to sort by this column
- * @private
- */
- ,sortable:false
-
- /**
- * @cfg {String} tplGroup Template for group actions
- * @private
- */
- ,tplGroup:
- '<tpl for="actions">'
- +'<div class="ux-grow-action-item<tpl if="\'right\'===align"> ux-action-right</tpl> '
- +'{cls}" style="{style}" qtip="{qtip}">{text}</div>'
- +'</tpl>'
-
- /**
- * @cfg {String} tplRow Template for row actions
- * @private
- */
- ,tplRow:
- '<div class="ux-row-action">'
- +'<tpl for="actions">'
- +'<div class="ux-row-action-item {cls} <tpl if="text">'
- +'ux-row-action-text</tpl>" style="{hide}{style}" qtip="{qtip}">'
- +'<tpl if="text"><span qtip="{qtip}">{text}</span></tpl></div>'
- +'</tpl>'
- +'</div>'
-
- /**
- * @cfg {String} hideMode How to hide hidden icons. Valid values are: 'visibility' and 'display'
- * (defaluts to 'visibility'). If the mode is visibility the hidden icon is not visible but there
- * is still blank space occupied by the icon. In display mode, the visible icons are shifted taking
- * the space of the hidden icon.
- */
- ,hideMode:'visibility'
-
- /**
- * @cfg {Number} widthIntercept Constant used for auto-width calculation (defaults to 4).
- * See {@link #autoWidth} for explanation.
- */
- ,widthIntercept:4
-
- /**
- * @cfg {Number} widthSlope Constant used for auto-width calculation (defaults to 21).
- * See {@link #autoWidth} for explanation.
- */
- ,widthSlope:21
- // }}}
-
- // methods
- // {{{
- /**
- * Init function
- * @param {Ext.grid.GridPanel} grid Grid this plugin is in
- */
- ,init:function(grid) {
- this.grid = grid;
-
- // the actions column must have an id for Ext 3.x
- this.id = this.id || Ext.id();
-
- // for Ext 3.x compatibility
- var lookup = grid.getColumnModel().lookup;
- delete(lookup[undefined]);
- lookup[this.id] = this;
-
- // {{{
- // setup template
- if(!this.tpl) {
- this.tpl = this.processActions(this.actions);
-
- } // eo template setup
- // }}}
-
- // calculate width
- if(this.autoWidth) {
- this.width = this.widthSlope * this.actions.length + this.widthIntercept;
- this.fixed = true;
- }
-
- // body click handler
- var view = grid.getView();
- var cfg = {scope:this};
- cfg[this.actionEvent] = this.onClick;
- grid.afterRender = grid.afterRender.createSequence(function() {
- view.mainBody.on(cfg);
- grid.on('destroy', this.purgeListeners, this);
- }, this);
-
- // setup renderer
- if(!this.renderer) {
- this.renderer = function(value, cell, record, row, col, store) {
- cell.css += (cell.css ? ' ' : '') + 'ux-row-action-cell';
- return this.tpl.apply(this.getData(value, cell, record, row, col, store));
- }.createDelegate(this);
- }
-
- // actions in grouping grids support
- if(view.groupTextTpl && this.groupActions) {
- view.interceptMouse = view.interceptMouse.createInterceptor(function(e) {
- if(e.getTarget('.ux-grow-action-item')) {
- return false;
- }
- });
- view.groupTextTpl =
- '<div class="ux-grow-action-text">' + view.groupTextTpl +'</div>'
- +this.processActions(this.groupActions, this.tplGroup).apply()
- ;
- }
-
- // cancel click
- if(true === this.keepSelection) {
- grid.processEvent = grid.processEvent.createInterceptor(function(name, e) {
- if('mousedown' === name) {
- return !this.getAction(e);
- }
- }, this);
- }
-
- } // eo function init
- // }}}
- // {{{
- /**
- * Returns data to apply to template. Override this if needed.
- * @param {Mixed} value
- * @param {Object} cell object to set some attributes of the grid cell
- * @param {Ext.data.Record} record from which the data is extracted
- * @param {Number} row row index
- * @param {Number} col col index
- * @param {Ext.data.Store} store object from which the record is extracted
- * @return {Object} data to apply to template
- */
- ,getData:function(value, cell, record, row, col, store) {
- return record.data || {};
- } // eo function getData
- // }}}
- // {{{
- /**
- * Processes actions configs and returns template.
- * @param {Array} actions
- * @param {String} template Optional. Template to use for one action item.
- * @return {String}
- * @private
- */
- ,processActions:function(actions, template) {
- var acts = [];
-
- // actions loop
- Ext.each(actions, function(a, i) {
- // save callback
- if(a.iconCls && 'function' === typeof (a.callback || a.cb)) {
- this.callbacks = this.callbacks || {};
- this.callbacks[a.iconCls] = a.callback || a.cb;
- }
-
- // data for intermediate template
- var o = {
- cls:a.iconIndex ? '{' + a.iconIndex + '}' : (a.iconCls ? a.iconCls : '')
- ,qtip:a.qtipIndex ? '{' + a.qtipIndex + '}' : (a.tooltip || a.qtip ? a.tooltip || a.qtip : '')
- ,text:a.textIndex ? '{' + a.textIndex + '}' : (a.text ? a.text : '')
- ,hide:a.hideIndex
- ? '<tpl if="' + a.hideIndex + '">'
- + ('display' === this.hideMode ? 'display:none' :'visibility:hidden') + ';</tpl>'
- : (a.hide ? ('display' === this.hideMode ? 'display:none' :'visibility:hidden;') : '')
- ,align:a.align || 'right'
- ,style:a.style ? a.style : ''
- };
- acts.push(o);
-
- }, this); // eo actions loop
-
- var xt = new Ext.XTemplate(template || this.tplRow);
- return new Ext.XTemplate(xt.apply({actions:acts}));
-
- } // eo function processActions
- // }}}
- ,getAction:function(e) {
- var action = false;
- var t = e.getTarget('.ux-row-action-item');
- if(t) {
- action = t.className.replace(/ux-row-action-item /, '');
- if(action) {
- action = action.replace(/ ux-row-action-text/, '');
- action = action.trim();
- }
- }
- return action;
- } // eo function getAction
- // {{{
- /**
- * Grid body actionEvent event handler
- * @private
- */
- ,onClick:function(e, target) {
-
- var view = this.grid.getView();
-
- // handle row action click
- var row = e.getTarget('.x-grid3-row');
- var col = view.findCellIndex(target.parentNode.parentNode);
- var action = this.getAction(e);
+ // handle row action click
+ var row = e.getTarget('.x-grid3-row');
+ var col = view.findCellIndex(target.parentNode.parentNode);
+ var action = this.getAction(e);
// var t = e.getTarget('.ux-row-action-item');
// if(t) {
// action = action.trim();
// }
// }
- if(false !== row && false !== col && false !== action) {
- var record = this.grid.store.getAt(row.rowIndex);
-
- // call callback if any
- if(this.callbacks && 'function' === typeof this.callbacks[action]) {
- this.callbacks[action](this.grid, record, action, row.rowIndex, col);
- }
-
- // fire events
- if(true !== this.eventsSuspended && false === this.fireEvent('beforeaction', this.grid, record, action, row.rowIndex, col)) {
- return;
- }
- else if(true !== this.eventsSuspended) {
- this.fireEvent('action', this.grid, record, action, row.rowIndex, col);
- }
-
- }
-
- // handle group action click
- t = e.getTarget('.ux-grow-action-item');
- if(t) {
- // get groupId
- var group = view.findGroup(target);
- var groupId = group ? group.id.replace(/ext-gen[0-9]+-gp-/, '') : null;
-
- // get matching records
- var records;
- if(groupId) {
- var re = new RegExp(RegExp.escape(groupId));
- records = this.grid.store.queryBy(function(r) {
- return r._groupId.match(re);
- });
- records = records ? records.items : [];
- }
- action = t.className.replace(/ux-grow-action-item (ux-action-right )*/, '');
-
- // call callback if any
- if('function' === typeof this.callbacks[action]) {
- this.callbacks[action](this.grid, records, action, groupId);
- }
-
- // fire events
- if(true !== this.eventsSuspended && false === this.fireEvent('beforegroupaction', this.grid, records, action, groupId)) {
- return false;
- }
- this.fireEvent('groupaction', this.grid, records, action, groupId);
- }
- } // eo function onClick
- // }}}
+ if (false !== row && false !== col && false !== action) {
+ var record = this.grid.store.getAt(row.rowIndex);
+
+ // call callback if any
+ if (this.callbacks && 'function' === typeof this.callbacks[action]) {
+ this.callbacks[action](this.grid, record, action, row.rowIndex, col);
+ }
+
+ // fire events
+ if (true !== this.eventsSuspended && false === this.fireEvent('beforeaction', this.grid, record, action, row.rowIndex, col)) {
+ return;
+ }
+ else if (true !== this.eventsSuspended) {
+ this.fireEvent('action', this.grid, record, action, row.rowIndex, col);
+ }
+
+ }
+
+ // handle group action click
+ t = e.getTarget('.ux-grow-action-item');
+ if (t) {
+ // get groupId
+ var group = view.findGroup(target);
+ var groupId = group ? group.id.replace(/ext-gen[0-9]+-gp-/, '') : null;
+
+ // get matching records
+ var records;
+ if (groupId) {
+ var re = new RegExp(RegExp.escape(groupId));
+ records = this.grid.store.queryBy(function(r) {
+ return r._groupId.match(re);
+ });
+ records = records ? records.items : [];
+ }
+ action = t.className.replace(/ux-grow-action-item (ux-action-right )*/, '');
+
+ // call callback if any
+ if ('function' === typeof this.callbacks[action]) {
+ this.callbacks[action](this.grid, records, action, groupId);
+ }
+
+ // fire events
+ if (true !== this.eventsSuspended && false === this.fireEvent('beforegroupaction', this.grid, records, action, groupId)) {
+ return false;
+ }
+ this.fireEvent('groupaction', this.grid, records, action, groupId);
+ }
+ } // eo function onClick
+ // }}}
});
*
* License details: http://www.gnu.org/licenses/lgpl.html
*/
-
+
/*global Ext */
// add RegExp.escape if it has not been already added
-if('function' !== typeof RegExp.escape) {
- RegExp.escape = function(s) {
- if('string' !== typeof s) {
- return s;
- }
- // Note: if pasting from forum, precede ]/\ with backslash manually
- return s.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
- }; // eo function escape
+if ('function' !== typeof RegExp.escape) {
+ RegExp.escape = function(s) {
+ if ('string' !== typeof s) {
+ return s;
+ }
+ // Note: if pasting from forum, precede ]/\ with backslash manually
+ return s.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+ }; // eo function escape
}
// create namespace
Ext.ns('Ext.ux.form');
-
+
/**
*
* @class Ext.ux.form.LovCombo
* @extends Ext.form.ComboBox
*/
Ext.ux.form.LovCombo = Ext.extend(Ext.form.ComboBox, {
-
- // {{{
- // configuration options
- /**
- * @cfg {String} checkField name of field used to store checked state.
- * It is automatically added to existing fields.
- * Change it only if it collides with your normal field.
- */
- checkField:'checked'
-
- /**
- * @cfg {String} separator separator to use between values and texts
- */
- ,separator:','
-
- /**
- * @cfg {String/Array} tpl Template for items.
- * Change it only if you know what you are doing.
- */
- // }}}
// {{{
- ,initComponent:function() {
-
- // template with checkbox
- if(!this.tpl) {
- this.tpl =
- '<tpl for=".">'
- +'<div class="x-combo-list-item">'
- +'<img src="' + Ext.BLANK_IMAGE_URL + '" '
- +'class="ux-lovcombo-icon ux-lovcombo-icon-'
- +'{[values.' + this.checkField + '?"checked":"unchecked"' + ']}">'
- +'<div class="ux-lovcombo-item-text">{' + (this.displayField || 'text' )+ '}</div>'
- +'</div>'
- +'</tpl>'
- ;
- }
-
+ // configuration options
+ /**
+ * @cfg {String} checkField name of field used to store checked state.
+ * It is automatically added to existing fields.
+ * Change it only if it collides with your normal field.
+ */
+ checkField: 'checked'
+
+ /**
+ * @cfg {String} separator separator to use between values and texts
+ */
+ , separator: ','
+
+ /**
+ * @cfg {String/Array} tpl Template for items.
+ * Change it only if you know what you are doing.
+ */
+ // }}}
+ // {{{
+ , initComponent: function() {
+
+ // template with checkbox
+ if (!this.tpl) {
+ this.tpl =
+ '<tpl for=".">'
+ + '<div class="x-combo-list-item">'
+ + '<img src="' + Ext.BLANK_IMAGE_URL + '" '
+ + 'class="ux-lovcombo-icon ux-lovcombo-icon-'
+ + '{[values.' + this.checkField + '?"checked":"unchecked"' + ']}">'
+ + '<div class="ux-lovcombo-item-text">{' + (this.displayField || 'text') + '}</div>'
+ + '</div>'
+ + '</tpl>'
+ ;
+ }
+
// call parent
Ext.ux.form.LovCombo.superclass.initComponent.apply(this, arguments);
- // install internal event handlers
- this.on({
- scope:this
- ,beforequery:this.onBeforeQuery
- ,blur:this.onRealBlur
- });
-
- // remove selection from input field
- this.onLoad = this.onLoad.createSequence(function() {
- if(this.el) {
- var v = this.el.dom.value;
- this.el.dom.value = '';
- this.el.dom.value = v;
- }
- });
-
+ // install internal event handlers
+ this.on({
+ scope: this
+ , beforequery: this.onBeforeQuery
+ , blur: this.onRealBlur
+ });
+
+ // remove selection from input field
+ this.onLoad = this.onLoad.createSequence(function() {
+ if (this.el) {
+ var v = this.el.dom.value;
+ this.el.dom.value = '';
+ this.el.dom.value = v;
+ }
+ });
+
} // e/o function initComponent
// }}}
- // {{{
- /**
- * Disables default tab key bahavior
- * @private
- */
- ,initEvents:function() {
- Ext.ux.form.LovCombo.superclass.initEvents.apply(this, arguments);
-
- // disable default tab handling - does no good
- this.keyNav.tab = false;
-
- } // eo function initEvents
- // }}}
- // {{{
- /**
- * clears value
- */
- ,clearValue:function() {
- this.value = '';
- this.setRawValue(this.value);
- this.store.clearFilter();
- this.store.each(function(r) {
- r.set(this.checkField, false);
- }, this);
- if(this.hiddenField) {
- this.hiddenField.value = '';
- }
- this.applyEmptyText();
- } // eo function clearValue
- // }}}
- // {{{
- /**
- * @return {String} separator (plus space) separated list of selected displayFields
- * @private
- */
- ,getCheckedDisplay:function() {
- var re = new RegExp(this.separator, "g");
- return this.getCheckedValue(this.displayField).replace(re, this.separator + ' ');
- } // eo function getCheckedDisplay
- // }}}
- // {{{
- /**
- * @return {String} separator separated list of selected valueFields
- * @private
- */
- ,getCheckedValue:function(field) {
- field = field || this.valueField;
- var c = [];
-
- // store may be filtered so get all records
- var snapshot = this.store.snapshot || this.store.data;
-
- snapshot.each(function(r) {
- if(r.get(this.checkField)) {
- c.push(r.get(field));
- }
- }, this);
-
- return c.join(this.separator);
- } // eo function getCheckedValue
- // }}}
- // {{{
- /**
- * beforequery event handler - handles multiple selections
- * @param {Object} qe query event
- * @private
- */
- ,onBeforeQuery:function(qe) {
- qe.query = qe.query.replace(new RegExp(this.getCheckedDisplay() + '[ ' + this.separator + ']*'), '');
- } // eo function onBeforeQuery
- // }}}
- // {{{
- /**
- * blur event handler - runs only when real blur event is fired
- */
- ,onRealBlur:function() {
- this.list.hide();
- var rv = this.getRawValue();
- var rva = rv.split(new RegExp(RegExp.escape(this.separator) + ' *'));
- var va = [];
- var snapshot = this.store.snapshot || this.store.data;
-
- // iterate through raw values and records and check/uncheck items
- Ext.each(rva, function(v) {
- snapshot.each(function(r) {
- if(v === r.get(this.displayField)) {
- va.push(r.get(this.valueField));
- }
- }, this);
- }, this);
- this.setValue(va.join(this.separator));
- this.store.clearFilter();
- } // eo function onRealBlur
- // }}}
- // {{{
- /**
- * Combo's onSelect override
- * @private
- * @param {Ext.data.Record} record record that has been selected in the list
- * @param {Number} index index of selected (clicked) record
- */
- ,onSelect:function(record, index) {
- if(this.fireEvent('beforeselect', this, record, index) !== false){
-
- // toggle checked field
- record.set(this.checkField, !record.get(this.checkField));
-
- // display full list
- if(this.store.isFiltered()) {
- this.doQuery(this.allQuery);
- }
-
- // set (update) value and fire event
- this.setValue(this.getCheckedValue());
+ // {{{
+ /**
+ * Disables default tab key bahavior
+ * @private
+ */
+ , initEvents: function() {
+ Ext.ux.form.LovCombo.superclass.initEvents.apply(this, arguments);
+
+ // disable default tab handling - does no good
+ this.keyNav.tab = false;
+
+ } // eo function initEvents
+ // }}}
+ // {{{
+ /**
+ * clears value
+ */
+ , clearValue: function() {
+ this.value = '';
+ this.setRawValue(this.value);
+ this.store.clearFilter();
+ this.store.each(function(r) {
+ r.set(this.checkField, false);
+ }, this);
+ if (this.hiddenField) {
+ this.hiddenField.value = '';
+ }
+ this.applyEmptyText();
+ } // eo function clearValue
+ // }}}
+ // {{{
+ /**
+ * @return {String} separator (plus space) separated list of selected displayFields
+ * @private
+ */
+ , getCheckedDisplay: function() {
+ var re = new RegExp(this.separator, "g");
+ return this.getCheckedValue(this.displayField).replace(re, this.separator + ' ');
+ } // eo function getCheckedDisplay
+ // }}}
+ // {{{
+ /**
+ * @return {String} separator separated list of selected valueFields
+ * @private
+ */
+ , getCheckedValue: function(field) {
+ field = field || this.valueField;
+ var c = [];
+
+ // store may be filtered so get all records
+ var snapshot = this.store.snapshot || this.store.data;
+
+ snapshot.each(function(r) {
+ if (r.get(this.checkField)) {
+ c.push(r.get(field));
+ }
+ }, this);
+
+ return c.join(this.separator);
+ } // eo function getCheckedValue
+ // }}}
+ // {{{
+ /**
+ * beforequery event handler - handles multiple selections
+ * @param {Object} qe query event
+ * @private
+ */
+ , onBeforeQuery: function(qe) {
+ qe.query = qe.query.replace(new RegExp(this.getCheckedDisplay() + '[ ' + this.separator + ']*'), '');
+ } // eo function onBeforeQuery
+ // }}}
+ // {{{
+ /**
+ * blur event handler - runs only when real blur event is fired
+ */
+ , onRealBlur: function() {
+ this.list.hide();
+ var rv = this.getRawValue();
+ var rva = rv.split(new RegExp(RegExp.escape(this.separator) + ' *'));
+ var va = [];
+ var snapshot = this.store.snapshot || this.store.data;
+
+ // iterate through raw values and records and check/uncheck items
+ Ext.each(rva, function(v) {
+ snapshot.each(function(r) {
+ if (v === r.get(this.displayField)) {
+ va.push(r.get(this.valueField));
+ }
+ }, this);
+ }, this);
+ this.setValue(va.join(this.separator));
+ this.store.clearFilter();
+ } // eo function onRealBlur
+ // }}}
+ // {{{
+ /**
+ * Combo's onSelect override
+ * @private
+ * @param {Ext.data.Record} record record that has been selected in the list
+ * @param {Number} index index of selected (clicked) record
+ */
+ , onSelect: function(record, index) {
+ if (this.fireEvent('beforeselect', this, record, index) !== false) {
+
+ // toggle checked field
+ record.set(this.checkField, !record.get(this.checkField));
+
+ // display full list
+ if (this.store.isFiltered()) {
+ this.doQuery(this.allQuery);
+ }
+
+ // set (update) value and fire event
+ this.setValue(this.getCheckedValue());
this.fireEvent('select', this, record, index);
}
- } // eo function onSelect
- // }}}
- // {{{
- /**
- * Sets the value of the LovCombo
- * @param {Mixed} v value
- */
- ,setValue:function(v) {
- if(v) {
- v = '' + v;
- if(this.valueField) {
- this.store.clearFilter();
- this.store.each(function(r) {
- var checked = !(!v.match(
- '(^|' + this.separator + ')' + RegExp.escape(r.get(this.valueField))
- +'(' + this.separator + '|$)'))
- ;
-
- r.set(this.checkField, checked);
- }, this);
- this.value = this.getCheckedValue();
- this.setRawValue(this.getCheckedDisplay());
- if(this.hiddenField) {
- this.hiddenField.value = this.value;
- }
- }
- else {
- this.value = v;
- this.setRawValue(v);
- if(this.hiddenField) {
- this.hiddenField.value = v;
- }
- }
- if(this.el) {
- this.el.removeClass(this.emptyClass);
- }
- }
- else {
- this.clearValue();
- }
- } // eo function setValue
- // }}}
- // {{{
- /**
- * Selects all items
- */
- ,selectAll:function() {
- this.store.each(function(record){
+ } // eo function onSelect
+ // }}}
+ // {{{
+ /**
+ * Sets the value of the LovCombo
+ * @param {Mixed} v value
+ */
+ , setValue: function(v) {
+ if (v) {
+ v = '' + v;
+ if (this.valueField) {
+ this.store.clearFilter();
+ this.store.each(function(r) {
+ var checked = !(!v.match(
+ '(^|' + this.separator + ')' + RegExp.escape(r.get(this.valueField))
+ + '(' + this.separator + '|$)'))
+ ;
+
+ r.set(this.checkField, checked);
+ }, this);
+ this.value = this.getCheckedValue();
+ this.setRawValue(this.getCheckedDisplay());
+ if (this.hiddenField) {
+ this.hiddenField.value = this.value;
+ }
+ }
+ else {
+ this.value = v;
+ this.setRawValue(v);
+ if (this.hiddenField) {
+ this.hiddenField.value = v;
+ }
+ }
+ if (this.el) {
+ this.el.removeClass(this.emptyClass);
+ }
+ }
+ else {
+ this.clearValue();
+ }
+ } // eo function setValue
+ // }}}
+ // {{{
+ /**
+ * Selects all items
+ */
+ , selectAll: function() {
+ this.store.each(function(record) {
// toggle checked field
record.set(this.checkField, true);
}, this);
this.doQuery(this.allQuery);
this.setValue(this.getCheckedValue());
} // eo full selectAll
- // }}}
- // {{{
- /**
- * Deselects all items. Synonym for clearValue
- */
- ,deselectAll:function() {
- this.clearValue();
+ // }}}
+ // {{{
+ /**
+ * Deselects all items. Synonym for clearValue
+ */
+ , deselectAll: function() {
+ this.clearValue();
} // eo full deselectAll
- // }}}
+ // }}}
}); // eo extend
-
+
// register xtype
-Ext.reg('lovcombo', Ext.ux.form.LovCombo);
+Ext.reg('lovcombo', Ext.ux.form.LovCombo);
*/
tvheadend.idnode_enum_stores = {}
-tvheadend.idnode_get_enum = function ( conf )
+tvheadend.idnode_get_enum = function(conf)
{
- /* Build key */
- var key = conf.url;
- if (conf.params)
- key += '?' + Ext.util.JSON.encode(conf.params);
- if (conf.event)
- key += '+' + conf.event;
-
- /* Use cached */
- if (key in tvheadend.idnode_enum_stores)
- return tvheadend.idnode_enum_stores[key];
-
- /* Build combobox */
- var st = new Ext.data.JsonStore({
- root : conf.root || 'entries',
- url : conf.url,
- baseParams : conf.params || {},
- fields : conf.fields || [ 'key', 'val' ],
- id : conf.id || 'key',
- autoLoad : true,
- sortInfo : {
- field : 'val',
- direction : 'ASC'
- }
- });
- tvheadend.idnode_enum_stores[key] = st;
-
- /* Event to update */
- if (conf.event) {
- tvheadend.comet.on(conf.event, function(){
- st.reload();
+ /* Build key */
+ var key = conf.url;
+ if (conf.params)
+ key += '?' + Ext.util.JSON.encode(conf.params);
+ if (conf.event)
+ key += '+' + conf.event;
+
+ /* Use cached */
+ if (key in tvheadend.idnode_enum_stores)
+ return tvheadend.idnode_enum_stores[key];
+
+ /* Build combobox */
+ var st = new Ext.data.JsonStore({
+ root: conf.root || 'entries',
+ url: conf.url,
+ baseParams: conf.params || {},
+ fields: conf.fields || ['key', 'val'],
+ id: conf.id || 'key',
+ autoLoad: true,
+ sortInfo: {
+ field: 'val',
+ direction: 'ASC'
+ }
});
- }
+ tvheadend.idnode_enum_stores[key] = st;
+
+ /* Event to update */
+ if (conf.event) {
+ tvheadend.comet.on(conf.event, function() {
+ st.reload();
+ });
+ }
- return st;
-}
+ return st;
+};
json_decode = function(d)
{
- if (d && d.responseText) {
- d = Ext.util.JSON.decode(d.responseText)
- if (d.entries)
- d = d.entries;
- if (d.nodes)
- d = d.nodes;
- } else {
- d = []
- }
- return d;
-}
+ if (d && d.responseText) {
+ d = Ext.util.JSON.decode(d.responseText);
+ if (d.entries)
+ d = d.entries;
+ if (d.nodes)
+ d = d.nodes;
+ } else {
+ d = [];
+ }
+ return d;
+};
/*
* Build enum data store
*/
tvheadend.idnode_enum_store = function(f)
{
- var store = null;
-
- /* API fetch */
- if (f.enum.type == 'api') {
- return tvheadend.idnode_get_enum({
- url : 'api/' + f.enum.uri,
- params : f.enum.params,
- event : f.enum.event
- });
- }
-
- switch (f.type) {
- case 'str':
- if (f.enum.length > 0 && f.enum[0] instanceof Object)
- store = new Ext.data.JsonStore({
- id : 'key',
- fields : [ 'key', 'val' ],
- data : f.enum,
+ var store = null;
+
+ /* API fetch */
+ if (f.enum.type === 'api') {
+ return tvheadend.idnode_get_enum({
+ url: 'api/' + f.enum.uri,
+ params: f.enum.params,
+ event: f.enum.event
});
- else
- store = f.enum;
- break;
- case 'int':
- case 'u32':
- case 'u16':
- case 'dbl':
- var data = null;
- if (f.enum.length > 0 && f.enum[0] instanceof Object) {
- data = f.enum;
- } else {
- data = []
- for ( i = 0; i < f.enum.length; i++ )
- data.push({ key: i, val: f.enum[i]});
- }
- store = new Ext.data.JsonStore({
- id : 'key',
- fields : [ 'key', 'val' ],
- data : data
- });
- break;
- }
- return store;
-}
-
-tvheadend.IdNodeField = function (conf)
-{
- /*
- * Properties
- */
- this.id = conf.id;
- this.text = conf.caption || this.id;
- this.type = conf.type;
- this.list = conf.list;
- this.rdonly = conf.rdonly;
- this.wronly = conf.wronly;
- this.wronce = conf.wronce;
- this.hidden = conf.hidden || conf.advanced;
- this.enum = conf.enum;
- this.store = null;
- if (this.enum)
- this.store = tvheadend.idnode_enum_store(this);
- this.ordered = false;
-
- /*
- * Methods
- */
-
- this.column = function ()
- {
- var w = 300;
- var ftype = 'string';
- if (this.type == 'int' || this.type == 'u32' ||
- this.type == 'u16' || this.type == 'dbl') {
- ftype = 'numeric';
- w = 80;
- } else if (this.type == 'bool') {
- ftype = 'boolean';
- w = 60;
}
- if (this.enum || this.list)
- w = 300;
- return {
- width : w,
- dataIndex: this.id,
- header : this.text,
- editor : this.editor({create: false}),
- renderer : this.renderer(),
- hidden : this.hidden,
- filter : {
- type : ftype,
- dataIndex : this.id
- }
- };
- }
-
- this.renderer = function ()
- {
- if (!this.store)
- return null;
-
- var st = this.store;
- return function (v) {
- if (st && st instanceof Ext.data.JsonStore) {
- var t = []
- var d;
- if (v.push)
- d = v;
- else
- d = [ v ];
- for (var i = 0; i < d.length; i++) {
- var r = st.find('key', d[i]);
- if (r != -1) {
- var nv = st.getAt(r).get('val');
- if (nv)
- t.push(nv);
- }
- }
- v = t.join(',');
- }
- return v;
- };
- }
-
- this.editor = function (conf)
- {
- var cons = null;
-
- /* Editable? */
- var d = this.rdonly;
- if (this.wronly && !conf.create)
- d = false;
-
- /* Basic */
- var c = {
- fieldLabel : this.text,
- name : this.id,
- value : conf.value || null,
- disabled : d,
- width : 300,
- };
-
- /* ComboBox */
- if (this.enum) {
- cons = Ext.form.ComboBox;
- if (this.list)
- cons = Ext.ux.form.LovCombo;
-
- /* Combo settings */
- c['mode'] = 'local';
- c['valueField'] = 'key';
- c['displayField'] = 'val';
- c['store'] = this.store;
- c['typeAhead'] = true;
- c['forceSelection'] = false;
- c['triggerAction'] = 'all',
- c['emptyText'] = 'Select ' + this.text + ' ...';
-
- /* Single */
- } else {
- switch (this.type) {
- case 'bool':
- cons = Ext.form.Checkbox;
- break;
+ switch (f.type) {
+ case 'str':
+ if (f.enum.length > 0 && f.enum[0] instanceof Object)
+ store = new Ext.data.JsonStore({
+ id: 'key',
+ fields: ['key', 'val'],
+ data: f.enum
+ });
+ else
+ store = f.enum;
+ break;
case 'int':
case 'u32':
case 'u16':
case 'dbl':
- cons = Ext.form.NumberField;
- break;
-
- default:
- cons = Ext.form.TextField;
- break;
- }
+ var data = null;
+ if (f.enum.length > 0 && f.enum[0] instanceof Object) {
+ data = f.enum;
+ } else {
+ data = [];
+ for (i = 0; i < f.enum.length; i++)
+ data.push({key: i, val: f.enum[i]});
+ }
+ store = new Ext.data.JsonStore({
+ id: 'key',
+ fields: ['key', 'val'],
+ data: data
+ });
+ break;
}
+ return store;
+};
- return new cons(c);
- }
-}
+tvheadend.IdNodeField = function(conf)
+{
+ /*
+ * Properties
+ */
+ this.id = conf.id;
+ this.text = conf.caption || this.id;
+ this.type = conf.type;
+ this.list = conf.list;
+ this.rdonly = conf.rdonly;
+ this.wronly = conf.wronly;
+ this.wronce = conf.wronce;
+ this.hidden = conf.hidden || conf.advanced;
+ this.enum = conf.enum;
+ this.store = null;
+ if (this.enum)
+ this.store = tvheadend.idnode_enum_store(this);
+ this.ordered = false;
+
+ /*
+ * Methods
+ */
+
+ this.column = function()
+ {
+ var w = 300;
+ var ftype = 'string';
+ if (this.type === 'int' || this.type === 'u32' ||
+ this.type === 'u16' || this.type === 'dbl') {
+ ftype = 'numeric';
+ w = 80;
+ } else if (this.type === 'bool') {
+ ftype = 'boolean';
+ w = 60;
+ }
+ if (this.enum || this.list)
+ w = 300;
+ return {
+ width: w,
+ dataIndex: this.id,
+ header: this.text,
+ editor: this.editor({create: false}),
+ renderer: this.renderer(),
+ hidden: this.hidden,
+ filter: {
+ type: ftype,
+ dataIndex: this.id
+ }
+ };
+ };
+
+ this.renderer = function()
+ {
+ if (!this.store)
+ return null;
+
+ var st = this.store;
+ return function(v) {
+ if (st && st instanceof Ext.data.JsonStore) {
+ var t = [];
+ var d;
+ if (v.push)
+ d = v;
+ else
+ d = [v];
+ for (var i = 0; i < d.length; i++) {
+ var r = st.find('key', d[i]);
+ if (r !== -1) {
+ var nv = st.getAt(r).get('val');
+ if (nv)
+ t.push(nv);
+ }
+ }
+ v = t.join(',');
+ }
+ return v;
+ };
+ };
+
+ this.editor = function(conf)
+ {
+ var cons = null;
+
+ /* Editable? */
+ var d = this.rdonly;
+ if (this.wronly && !conf.create)
+ d = false;
+
+ /* Basic */
+ var c = {
+ fieldLabel: this.text,
+ name: this.id,
+ value: conf.value || null,
+ disabled: d,
+ width: 300
+ };
+
+ /* ComboBox */
+ if (this.enum) {
+ cons = Ext.form.ComboBox;
+ if (this.list)
+ cons = Ext.ux.form.LovCombo;
+
+ /* Combo settings */
+ c['mode'] = 'local';
+ c['valueField'] = 'key';
+ c['displayField'] = 'val';
+ c['store'] = this.store;
+ c['typeAhead'] = true;
+ c['forceSelection'] = false;
+ c['triggerAction'] = 'all',
+ c['emptyText'] = 'Select ' + this.text + ' ...';
+
+ /* Single */
+ } else {
+ switch (this.type) {
+ case 'bool':
+ cons = Ext.form.Checkbox;
+ break;
+
+ case 'int':
+ case 'u32':
+ case 'u16':
+ case 'dbl':
+ cons = Ext.form.NumberField;
+ break;
+
+ default:
+ cons = Ext.form.TextField;
+ break;
+ }
+ }
+
+ return new cons(c);
+ };
+};
/*
* IdNode
*/
-tvheadend.IdNode = function (conf)
+tvheadend.IdNode = function(conf)
{
- /*
- * Properties
- */
- this.clazz = conf.class;
- this.text = conf.caption || this.clazz;
- this.props = conf.props;
- this.order = [];
- this.fields = [];
- for (var i = 0; i < this.props.length; i++) {
- this.fields.push(new tvheadend.IdNodeField(this.props[i]));
- }
- var o = [];
- if (conf.order)
- o = conf.order.split(',');
- if (o) {
- while (o.length < this.fields.length)
- o.push(null);
- for (var i = 0; i < o.length; i++) {
- this.order[i] = null;
- if (o[i]) {
- for (var j = 0; j < this.fields.length; j++) {
- if (this.fields[j].id == o[i]) {
- this.order[i] = this.fields[j];
- this.fields[j].ordered = true;
- break;
- }
- }
- }
+ /*
+ * Properties
+ */
+ this.clazz = conf.class;
+ this.text = conf.caption || this.clazz;
+ this.props = conf.props;
+ this.order = [];
+ this.fields = [];
+ for (var i = 0; i < this.props.length; i++) {
+ this.fields.push(new tvheadend.IdNodeField(this.props[i]));
}
- for (var i = 0; i < o.length; i++) {
- if (this.order[i] == null) {
- for (var j = 0; j < this.fields.length; j++) {
- if (!this.fields[j].ordered) {
- this.fields[j].ordered = true;
- this.order[i] = this.fields[j];
- break;
- }
+ var o = [];
+ if (conf.order)
+ o = conf.order.split(',');
+ if (o) {
+ while (o.length < this.fields.length)
+ o.push(null);
+ for (var i = 0; i < o.length; i++) {
+ this.order[i] = null;
+ if (o[i]) {
+ for (var j = 0; j < this.fields.length; j++) {
+ if (this.fields[j].id === o[i]) {
+ this.order[i] = this.fields[j];
+ this.fields[j].ordered = true;
+ break;
+ }
+ }
+ }
+ }
+ for (var i = 0; i < o.length; i++) {
+ if (this.order[i] == null) {
+ for (var j = 0; j < this.fields.length; j++) {
+ if (!this.fields[j].ordered) {
+ this.fields[j].ordered = true;
+ this.order[i] = this.fields[j];
+ break;
+ }
+ }
+ }
}
- }
}
- }
- /*
- * Methods
- */
+ /*
+ * Methods
+ */
+
+ this.length = function() {
+ return this.fields.length;
+ };
- this.length = function () {
- return this.fields.length;
- }
-
- this.field = function ( index ) {
- if (this.order) return this.order[index]; else return this.fields[index];
- }
-}
+ this.field = function(index) {
+ if (this.order)
+ return this.order[index];
+ else
+ return this.fields[index];
+ };
+};
/*
*/
tvheadend.idnode_editor_field = function(f, create)
{
- var d = f.rdonly || false;
- if (f.wronly && !create) d = false;
- var value = f.value;
- if (value == null)
- value = f.default;
-
- /* Enumerated (combobox) type */
- if (f.enum) {
- var cons = Ext.form.ComboBox;
- if (f.list)
- cons = Ext.ux.form.LovCombo;
- var st = tvheadend.idnode_enum_store(f);
- var r = new cons({
- fieldLabel : f.caption,
- name : f.id,
- value : value,
- disabled : d,
- width : 300,
- mode : 'local',
- valueField : 'key',
- displayField : 'val',
- store : st,
- typeAhead : true, // TODO: this does strange things in multi
- forceSelection : false,
- triggerAction : 'all',
- emptyText :'Select ' + f.caption +' ...',
- listeners : {
- beforequery: function(qe){
- delete qe.combo.lastQuery;
+ var d = f.rdonly || false;
+ if (f.wronly && !create)
+ d = false;
+ var value = f.value;
+ if (value == null)
+ value = f.default;
+
+ /* Enumerated (combobox) type */
+ if (f.enum) {
+ var cons = Ext.form.ComboBox;
+ if (f.list)
+ cons = Ext.ux.form.LovCombo;
+ var st = tvheadend.idnode_enum_store(f);
+ var r = new cons({
+ fieldLabel: f.caption,
+ name: f.id,
+ value: value,
+ disabled: d,
+ width: 300,
+ mode: 'local',
+ valueField: 'key',
+ displayField: 'val',
+ store: st,
+ typeAhead: true, // TODO: this does strange things in multi
+ forceSelection: false,
+ triggerAction: 'all',
+ emptyText: 'Select ' + f.caption + ' ...',
+ listeners: {
+ beforequery: function(qe) {
+ delete qe.combo.lastQuery;
+ }
+ }
+ });
+ if (st.on) {
+ var fn = function() {
+ st.un('load', fn);
+ r.setValue(value); // HACK: to get extjs to display properly
+ };
+ st.on('load', fn);
}
- }
- });
- if (st.on) {
- var fn = function() {
- st.un('load', fn);
- r.setValue(value); // HACK: to get extjs to display properly
- };
- st.on('load', fn);
+ return r;
+ /* TODO: listeners for regexp?
+ listeners : {
+ keyup: function() {
+ this.store.filter('val', this.getRawValue(), true, false);
+ },
+ beforequery: function(queryEvent) {
+ queryEvent.combo.onLoad();
+ // prevent doQuery from firing and clearing out my filter.
+ return false;
+ }
+ }
+ */
}
- return r;
- /* TODO: listeners for regexp?
- listeners : {
- keyup: function() {
- this.store.filter('val', this.getRawValue(), true, false);
- },
- beforequery: function(queryEvent) {
- queryEvent.combo.onLoad();
- // prevent doQuery from firing and clearing out my filter.
- return false;
- }
+
+ /* Singular */
+ switch (f.type) {
+ case 'str':
+ return new Ext.form.TextField({
+ fieldLabel: f.caption,
+ name: f.id,
+ value: value,
+ disabled: d,
+ width: 300
+ });
+ break;
+
+ case 'bool':
+ return new Ext.ux.form.XCheckbox({
+ fieldLabel: f.caption,
+ name: f.id,
+ checked: value,
+ disabled: d
+ });
+ break;
+
+ case 'int':
+ case 'u32':
+ case 'u16':
+ case 'dbl':
+ return new Ext.form.NumberField({
+ fieldLabel: f.caption,
+ name: f.id,
+ value: value,
+ disabled: d,
+ width: 300
+ });
+ break;
}
- */
- }
-
- /* Singular */
- switch(f.type) {
- case 'str':
- return new Ext.form.TextField({
- fieldLabel : f.caption,
- name : f.id,
- value : value,
- disabled : d,
- width : 300
- });
- break;
-
- case 'bool':
- return new Ext.ux.form.XCheckbox({
- fieldLabel : f.caption,
- name : f.id,
- checked : value,
- disabled : d
- });
- break;
-
- case 'int':
- case 'u32':
- case 'u16':
- case 'dbl':
- return new Ext.form.NumberField({
- fieldLabel : f.caption,
- name : f.id,
- value : value,
- disabled : d,
- width : 300
- });
- break;
- }
- return null;
-}
+ return null;
+};
/*
* ID node editor form fields
*/
-tvheadend.idnode_editor_form = function ( d, panel )
+tvheadend.idnode_editor_form = function(d, panel)
{
- var af = [];
- var rf = [];
- var df = [];
-
- /* Fields */
- for (var i = 0; i < d.length; i++) {
- var f = tvheadend.idnode_editor_field(d[i]);
- if (!f) continue;
- if (d[i].rdonly)
- rf.push(f)
- else if (d[i].advanced)
- af.push(f);
- else
- df.push(f);
- }
- if (df.length) {
- panel.add(new Ext.form.FieldSet({
- title : 'Basic Settings',
- autoHeight : true,
- autoWidth : true,
- collapsible : true,
- collapsed : false,
- items : df
- }));
- }
- if (af.length) {
- panel.add(new Ext.form.FieldSet({
- title : 'Advanced Settings',
- autoHeight : true,
- autoWidth : true,
- collapsible : true,
- collapsed : false,//true,
- items : af
- }));
- }
- if (rf.length) {
- panel.add(new Ext.form.FieldSet({
- title : 'Read-only Info',
- autoHeight : true,
- autoWidth : true,
- collapsible : true,
- collapsed : false,//true,
- items : rf
- }));
- }
- panel.doLayout();
-}
+ var af = [];
+ var rf = [];
+ var df = [];
+
+ /* Fields */
+ for (var i = 0; i < d.length; i++) {
+ var f = tvheadend.idnode_editor_field(d[i]);
+ if (!f)
+ continue;
+ if (d[i].rdonly)
+ rf.push(f);
+ else if (d[i].advanced)
+ af.push(f);
+ else
+ df.push(f);
+ }
+ if (df.length) {
+ panel.add(new Ext.form.FieldSet({
+ title: 'Basic Settings',
+ autoHeight: true,
+ autoWidth: true,
+ collapsible: true,
+ collapsed: false,
+ items: df
+ }));
+ }
+ if (af.length) {
+ panel.add(new Ext.form.FieldSet({
+ title: 'Advanced Settings',
+ autoHeight: true,
+ autoWidth: true,
+ collapsible: true,
+ collapsed: false, //true,
+ items: af
+ }));
+ }
+ if (rf.length) {
+ panel.add(new Ext.form.FieldSet({
+ title: 'Read-only Info',
+ autoHeight: true,
+ autoWidth: true,
+ collapsible: true,
+ collapsed: false, //true,
+ items: rf
+ }));
+ }
+ panel.doLayout();
+};
/*
* ID node editor panel
*/
tvheadend.idnode_editor = function(item, conf)
{
- var panel = null;
- var buttons = [];
-
- /* Buttons */
- var saveBtn = new Ext.Button({
- text : 'Save',
- handler : function() {
- var node = panel.getForm().getFieldValues();
- node.uuid = item.uuid;
- Ext.Ajax.request({
- url : 'api/idnode/save',
- params : {
- node: Ext.encode(node)
- },
- success : function(d) {
- if (conf.win) conf.win.hide();
+ var panel = null;
+ var buttons = [];
+
+ /* Buttons */
+ var saveBtn = new Ext.Button({
+ text: 'Save',
+ handler: function() {
+ var node = panel.getForm().getFieldValues();
+ node.uuid = item.uuid;
+ Ext.Ajax.request({
+ url: 'api/idnode/save',
+ params: {
+ node: Ext.encode(node)
+ },
+ success: function(d) {
+ if (conf.win)
+ conf.win.hide();
+ }
+ });
}
- });
+ });
+ buttons.push(saveBtn);
+
+ if (conf.help) {
+ var helpBtn = new Ext.Button({
+ text: 'Help',
+ handler: conf.help
+ });
+ buttons.push(helpBtn);
}
- });
- buttons.push(saveBtn);
- if (conf.help) {
- var helpBtn = new Ext.Button({
- text : 'Help',
- handler : conf.help
+ panel = new Ext.FormPanel({
+ title: conf.title || null,
+ frame: true,
+ border: true,
+ bodyStyle: 'padding: 5px',
+ labelAlign: 'left',
+ labelWidth: 200,
+ autoWidth: true,
+ autoHeight: !conf.fixedHeight,
+ width: 600,
+ //defaults: {width: 330},
+ defaultType: 'textfield',
+ buttonAlign: 'left',
+ buttons: buttons
});
- buttons.push(helpBtn);
- }
-
- panel = new Ext.FormPanel({
- title : conf.title || null,
- frame : true,
- border : true,
- bodyStyle : 'padding: 5px',
- labelAlign : 'left',
- labelWidth : 200,
- autoWidth : true,
- autoHeight : !conf.fixedHeight,
- width : 600,
- //defaults: {width: 330},
- defaultType : 'textfield',
- buttonAlign : 'left',
- buttons : buttons
- });
-
- tvheadend.idnode_editor_form(item.props || item.params, panel);
-
- return panel;
-}
+
+ tvheadend.idnode_editor_form(item.props || item.params, panel);
+
+ return panel;
+};
/*
*/
tvheadend.idnode_create = function(conf)
{
- var puuid = null;
- var panel = null;
- var pclass = null;
-
- /* Buttons */
- var saveBtn = new Ext.Button({
- tooltip : 'Create new entry',
- text : 'Create',
- hidden : true,
- handler : function(){
- params = conf.create.params || {}
- if (puuid)
- params['uuid'] = puuid;
- if (pclass)
- params['class'] = pclass
- params['conf'] = Ext.encode(panel.getForm().getFieldValues());
- Ext.Ajax.request({
- url : conf.create.url || conf.url + '/create',
- params : params,
- success : function(d) {
- win.close();
+ var puuid = null;
+ var panel = null;
+ var pclass = null;
+
+ /* Buttons */
+ var saveBtn = new Ext.Button({
+ tooltip: 'Create new entry',
+ text: 'Create',
+ hidden: true,
+ handler: function() {
+ params = conf.create.params || {};
+ if (puuid)
+ params['uuid'] = puuid;
+ if (pclass)
+ params['class'] = pclass;
+ params['conf'] = Ext.encode(panel.getForm().getFieldValues());
+ Ext.Ajax.request({
+ url: conf.create.url || conf.url + '/create',
+ params: params,
+ success: function(d) {
+ win.close();
+ }
+ });
}
- });
- }
- });
- var undoBtn = new Ext.Button({
- tooltip : 'Cancel operation',
- text : 'Cancel',
- handler : function(){
- win.close();
- }
- });
-
- /* Form */
- panel = new Ext.FormPanel({
- frame : true,
- border : true,
- bodyStyle : 'padding: 5px',
- labelAlign : 'left',
- labelWidth : 200,
- autoWidth : true,
- autoHeight : true,
- defaultType : 'textfield',
- buttonAlign : 'left',
- items : [],
- buttons : [ undoBtn, saveBtn ]
- });
-
- /* Create window */
- win = new Ext.Window({
- title : 'Add ' + conf.titleS,
- layout : 'fit',
- autoWidth : true,
- autoHeight : true,
- plain : true,
- items : panel
- });
-
-
- /* Do we need to first select a class? */
- if (conf.select) {
- var store = conf.select.store;
- if (!store) {
- store = new Ext.data.JsonStore({
- root : 'entries',
- url : conf.select.url || conf.url,
- baseParams : conf.select.params,
- fields : [ conf.select.valueField, conf.select.displayField ]
- });
- }
- var select = null;
- if (conf.select.propField) {
- select = function (s, n, o) {
- var r = store.getAt(s.selectedIndex);
- if (r) {
- var d = r.get(conf.select.propField);
- if (d) {
- pclass = r.get(conf.select.valueField);
- win.setTitle('Add ' + s.lastSelectionText);
- panel.remove(s);
- tvheadend.idnode_editor_form(d, panel);
- saveBtn.setVisible(true);
- }
+ });
+ var undoBtn = new Ext.Button({
+ tooltip: 'Cancel operation',
+ text: 'Cancel',
+ handler: function() {
+ win.close();
}
- }
- } else {
- select = function (s, n, o) {
- params = conf.select.clazz.params || {};
- params['uuid'] = puuid = n.id;
- Ext.Ajax.request({
- url : conf.select.clazz.url || conf.select.url || conf.url,
- success : function(d) {
- panel.remove(s);
- d = json_decode(d);
- tvheadend.idnode_editor_form(d.props, panel);
- saveBtn.setVisible(true);
- },
- params : params
- });
- };
- }
+ });
- /* Parent selector */
- var combo = new Ext.form.ComboBox({
- fieldLabel : conf.select.label,
- grow : true,
- editable : false,
- allowBlank : false,
- displayField : conf.select.displayField,
- valueField : conf.select.valueField,
- mode : 'remote',
- triggerAction : 'all',
- store : store,
- listeners : {
- select : select
- }
+ /* Form */
+ panel = new Ext.FormPanel({
+ frame: true,
+ border: true,
+ bodyStyle: 'padding: 5px',
+ labelAlign: 'left',
+ labelWidth: 200,
+ autoWidth: true,
+ autoHeight: true,
+ defaultType: 'textfield',
+ buttonAlign: 'left',
+ items: [],
+ buttons: [undoBtn, saveBtn]
});
- panel.add(combo);
- win.show();
- } else {
- Ext.Ajax.request({
- url : conf.url + '/class',
- params : conf.params,
- success : function(d) {
- d = json_decode(d);
- tvheadend.idnode_editor_form(d.props, panel);
- saveBtn.setVisible(true);
- win.show();
- }
+ /* Create window */
+ win = new Ext.Window({
+ title: 'Add ' + conf.titleS,
+ layout: 'fit',
+ autoWidth: true,
+ autoHeight: true,
+ plain: true,
+ items: panel
});
- }
-}
+
+
+ /* Do we need to first select a class? */
+ if (conf.select) {
+ var store = conf.select.store;
+ if (!store) {
+ store = new Ext.data.JsonStore({
+ root: 'entries',
+ url: conf.select.url || conf.url,
+ baseParams: conf.select.params,
+ fields: [conf.select.valueField, conf.select.displayField]
+ });
+ }
+ var select = null;
+ if (conf.select.propField) {
+ select = function(s, n, o) {
+ var r = store.getAt(s.selectedIndex);
+ if (r) {
+ var d = r.get(conf.select.propField);
+ if (d) {
+ pclass = r.get(conf.select.valueField);
+ win.setTitle('Add ' + s.lastSelectionText);
+ panel.remove(s);
+ tvheadend.idnode_editor_form(d, panel);
+ saveBtn.setVisible(true);
+ }
+ }
+ };
+ } else {
+ select = function(s, n, o) {
+ params = conf.select.clazz.params || {};
+ params['uuid'] = puuid = n.id;
+ Ext.Ajax.request({
+ url: conf.select.clazz.url || conf.select.url || conf.url,
+ success: function(d) {
+ panel.remove(s);
+ d = json_decode(d);
+ tvheadend.idnode_editor_form(d.props, panel);
+ saveBtn.setVisible(true);
+ },
+ params: params
+ });
+ };
+ }
+
+ /* Parent selector */
+ var combo = new Ext.form.ComboBox({
+ fieldLabel: conf.select.label,
+ grow: true,
+ editable: false,
+ allowBlank: false,
+ displayField: conf.select.displayField,
+ valueField: conf.select.valueField,
+ mode: 'remote',
+ triggerAction: 'all',
+ store: store,
+ listeners: {
+ select: select
+ }
+ });
+
+ panel.add(combo);
+ win.show();
+ } else {
+ Ext.Ajax.request({
+ url: conf.url + '/class',
+ params: conf.params,
+ success: function(d) {
+ d = json_decode(d);
+ tvheadend.idnode_editor_form(d.props, panel);
+ saveBtn.setVisible(true);
+ win.show();
+ }
+ });
+ }
+};
/*
*/
tvheadend.idnode_grid = function(panel, conf)
{
- function build (d)
- {
- var columns = conf.lcol || [];
- var filters = [];
- var fields = [];
- var buttons = [];
- var plugins = conf.plugins || [];
- var saveBtn = null;
- var undoBtn = null;
- var addBtn = null;
- var delBtn = null;
- var upBtn = null;
- var downBtn = null;
- var editBtn = null;
-
- /* Model */
- var idnode = new tvheadend.IdNode(d);
- for (var i = 0; i < idnode.length(); i++) {
- var f = idnode.field(i);
- var c = f.column();
- fields.push(f.id);
- columns.push(c);
- if (c.filter)
- filters.push(c.filter);
- }
+ function build(d)
+ {
+ var columns = conf.lcol || [];
+ var filters = [];
+ var fields = [];
+ var buttons = [];
+ var plugins = conf.plugins || [];
+ var saveBtn = null;
+ var undoBtn = null;
+ var addBtn = null;
+ var delBtn = null;
+ var upBtn = null;
+ var downBtn = null;
+ var editBtn = null;
+
+ /* Model */
+ var idnode = new tvheadend.IdNode(d);
+ for (var i = 0; i < idnode.length(); i++) {
+ var f = idnode.field(i);
+ var c = f.column();
+ fields.push(f.id);
+ columns.push(c);
+ if (c.filter)
+ filters.push(c.filter);
+ }
- /* Right-hand columns */
- if (conf.rcol)
- for (i = 0; i < conf.rcol.length; i++)
- columns.push(conf.rcol[i])
+ /* Right-hand columns */
+ if (conf.rcol)
+ for (i = 0; i < conf.rcol.length; i++)
+ columns.push(conf.rcol[i]);
- /* Filters */
- var filter = new Ext.ux.grid.GridFilters({
- encode : true,
- local : false,
- filters : filters
- });
+ /* Filters */
+ var filter = new Ext.ux.grid.GridFilters({
+ encode: true,
+ local: false,
+ filters: filters
+ });
- var sort = null;
- if (conf.sort)
- sort = conf.sort;
-
- /* Store */
- var store = new Ext.data.JsonStore({
- root : 'entries',
- url : conf.url + '/grid',
- autoLoad : true,
- id : 'uuid',
- totalProperty : 'total',
- fields : fields,
- remoteSort : true,
- pruneModifiedRecords : true,
- sortInfo : sort
- });
+ var sort = null;
+ if (conf.sort)
+ sort = conf.sort;
+
+ /* Store */
+ var store = new Ext.data.JsonStore({
+ root: 'entries',
+ url: conf.url + '/grid',
+ autoLoad: true,
+ id: 'uuid',
+ totalProperty: 'total',
+ fields: fields,
+ remoteSort: true,
+ pruneModifiedRecords: true,
+ sortInfo: sort
+ });
- /* Model */
- var sortable = true;
- if (conf.move)
- sortable = false;
- var model = new Ext.grid.ColumnModel({
- defaultSortable : sortable,
- columns : columns
- });
+ /* Model */
+ var sortable = true;
+ if (conf.move)
+ sortable = false;
+ var model = new Ext.grid.ColumnModel({
+ defaultSortable: sortable,
+ columns: columns
+ });
- /* Selection */
- var select = new Ext.grid.RowSelectionModel({
- singleSelect : false
- });
+ /* Selection */
+ var select = new Ext.grid.RowSelectionModel({
+ singleSelect: false
+ });
- /* Event handlers */
- store.on('update', function(s, r, o){
- var d = (s.getModifiedRecords().length == 0);
- undoBtn.setDisabled(d);
- saveBtn.setDisabled(d);
- });
- select.on('selectionchange', function(s){
- if (delBtn)
- delBtn.setDisabled(s.getCount() == 0);
- if (upBtn) {
- upBtn.setDisabled(s.getCount() == 0);
- downBtn.setDisabled(s.getCount() == 0);
- }
- editBtn.setDisabled(s.getCount() != 1);
- if (conf.selected)
- conf.selected(s);
- });
+ /* Event handlers */
+ store.on('update', function(s, r, o) {
+ var d = (s.getModifiedRecords().length === 0);
+ undoBtn.setDisabled(d);
+ saveBtn.setDisabled(d);
+ });
+ select.on('selectionchange', function(s) {
+ if (delBtn)
+ delBtn.setDisabled(s.getCount() === 0);
+ if (upBtn) {
+ upBtn.setDisabled(s.getCount() === 0);
+ downBtn.setDisabled(s.getCount() === 0);
+ }
+ editBtn.setDisabled(s.getCount() !== 1);
+ if (conf.selected)
+ conf.selected(s);
+ });
- /* Top bar */
- saveBtn = new Ext.Toolbar.Button({
- tooltip : 'Save pending changes (marked with red border)',
- iconCls : 'save',
- text : 'Save',
- disabled : true,
- handler : function(){
- var mr = store.getModifiedRecords();
- var out = new Array();
- for (var x = 0; x < mr.length; x++) {
- v = mr[x].getChanges();
- out[x] = v;
- out[x].uuid = mr[x].id;
- }
- Ext.Ajax.request({
- url : 'api/idnode/save',
- params : {
- node: Ext.encode(out)
- },
- success : function(d)
- {
- if (!auto.getValue()) store.reload();
- }
+ /* Top bar */
+ saveBtn = new Ext.Toolbar.Button({
+ tooltip: 'Save pending changes (marked with red border)',
+ iconCls: 'save',
+ text: 'Save',
+ disabled: true,
+ handler: function() {
+ var mr = store.getModifiedRecords();
+ var out = new Array();
+ for (var x = 0; x < mr.length; x++) {
+ v = mr[x].getChanges();
+ out[x] = v;
+ out[x].uuid = mr[x].id;
+ }
+ Ext.Ajax.request({
+ url: 'api/idnode/save',
+ params: {
+ node: Ext.encode(out)
+ },
+ success: function(d)
+ {
+ if (!auto.getValue())
+ store.reload();
+ }
+ });
+ }
});
- }
- });
- buttons.push(saveBtn);
- undoBtn = new Ext.Toolbar.Button({
- tooltip : 'Revert pending changes (marked with red border)',
- iconCls : 'undo',
- text : 'Undo',
- disabled : true,
- handler : function() {
- store.rejectChanges();
- }
- });
- buttons.push(undoBtn);
- buttons.push('-');
- if (conf.add) {
- addBtn = new Ext.Toolbar.Button({
- tooltip : 'Add a new entry',
- iconCls : 'add',
- text : 'Add',
- disabled : false,
- handler : function() {
- tvheadend.idnode_create(conf.add);
- }
- });
- buttons.push(addBtn);
- }
- if (conf.del) {
- delBtn = new Ext.Toolbar.Button({
- tooltip : 'Delete selected entries',
- iconCls : 'remove',
- text : 'Delete',
- disabled : true,
- handler : function() {
- var r = select.getSelections();
- if (r && r.length > 0) {
- var uuids = []
- for ( var i = 0; i < r.length; i++ )
- uuids.push(r[i].id)
- Ext.Ajax.request({
- url : 'api/idnode/delete',
- params : {
- uuid: Ext.encode(uuids)
- },
- success : function(d)
- {
- if (!auto.getValue()) store.reload();
- }
+ buttons.push(saveBtn);
+ undoBtn = new Ext.Toolbar.Button({
+ tooltip: 'Revert pending changes (marked with red border)',
+ iconCls: 'undo',
+ text: 'Undo',
+ disabled: true,
+ handler: function() {
+ store.rejectChanges();
+ }
+ });
+ buttons.push(undoBtn);
+ buttons.push('-');
+ if (conf.add) {
+ addBtn = new Ext.Toolbar.Button({
+ tooltip: 'Add a new entry',
+ iconCls: 'add',
+ text: 'Add',
+ disabled: false,
+ handler: function() {
+ tvheadend.idnode_create(conf.add);
+ }
});
- }
+ buttons.push(addBtn);
}
- });
- buttons.push(delBtn);
- }
- if (conf.move) {
- upBtn = new Ext.Toolbar.Button({
- tooltip : 'Move selected entries up',
- iconCls : 'moveup',
- text : 'Move Up',
- disabled : true,
- handler : function() {
- var r = select.getSelections();
- if (r && r.length > 0) {
- var uuids = []
- for ( var i = 0; i < r.length; i++ )
- uuids.push(r[i].id)
- Ext.Ajax.request({
- url : 'api/idnode/moveup',
- params : {
- uuid: Ext.encode(uuids)
- },
- success : function(d)
- {
- store.reload();
- }
+ if (conf.del) {
+ delBtn = new Ext.Toolbar.Button({
+ tooltip: 'Delete selected entries',
+ iconCls: 'remove',
+ text: 'Delete',
+ disabled: true,
+ handler: function() {
+ var r = select.getSelections();
+ if (r && r.length > 0) {
+ var uuids = [];
+ for (var i = 0; i < r.length; i++)
+ uuids.push(r[i].id);
+ Ext.Ajax.request({
+ url: 'api/idnode/delete',
+ params: {
+ uuid: Ext.encode(uuids)
+ },
+ success: function(d)
+ {
+ if (!auto.getValue())
+ store.reload();
+ }
+ });
+ }
+ }
});
- }
+ buttons.push(delBtn);
}
- });
- buttons.push(upBtn);
- downBtn = new Ext.Toolbar.Button({
- tooltip : 'Move selected entries down',
- iconCls : 'movedown',
- text : 'Move Down',
- disabled : true,
- handler : function() {
- var r = select.getSelections();
- if (r && r.length > 0) {
- var uuids = []
- for ( var i = 0; i < r.length; i++ )
- uuids.push(r[i].id)
- Ext.Ajax.request({
- url : 'api/idnode/movedown',
- params : {
- uuid: Ext.encode(uuids)
- },
- success : function(d)
- {
- store.reload();
- }
+ if (conf.move) {
+ upBtn = new Ext.Toolbar.Button({
+ tooltip: 'Move selected entries up',
+ iconCls: 'moveup',
+ text: 'Move Up',
+ disabled: true,
+ handler: function() {
+ var r = select.getSelections();
+ if (r && r.length > 0) {
+ var uuids = [];
+ for (var i = 0; i < r.length; i++)
+ uuids.push(r[i].id);
+ Ext.Ajax.request({
+ url: 'api/idnode/moveup',
+ params: {
+ uuid: Ext.encode(uuids)
+ },
+ success: function(d)
+ {
+ store.reload();
+ }
+ });
+ }
+ }
});
- }
- }
- });
- buttons.push(downBtn);
- }
- if (conf.add || conf.del || conf.move)
- buttons.push('-');
- editBtn = new Ext.Toolbar.Button({
- tooltip : 'Edit selected entry',
- iconCls : 'edit',
- text : 'Edit',
- disabled : true,
- handler : function() {
- var r = select.getSelected();
- if (r) {
- if (conf.edittree) {
- var p = tvheadend.idnode_tree({
- url : 'api/idnode/tree',
- params : {
- root : r.id
- }
- });
- p.setSize(800,600);
- var w = new Ext.Window({
- title : 'Edit ' + conf.titleS,
- layout : 'fit',
- autoWidth : true,
- autoHeight : true,
- plain : true,
- items : p
+ buttons.push(upBtn);
+ downBtn = new Ext.Toolbar.Button({
+ tooltip: 'Move selected entries down',
+ iconCls: 'movedown',
+ text: 'Move Down',
+ disabled: true,
+ handler: function() {
+ var r = select.getSelections();
+ if (r && r.length > 0) {
+ var uuids = [];
+ for (var i = 0; i < r.length; i++)
+ uuids.push(r[i].id);
+ Ext.Ajax.request({
+ url: 'api/idnode/movedown',
+ params: {
+ uuid: Ext.encode(uuids)
+ },
+ success: function(d)
+ {
+ store.reload();
+ }
+ });
+ }
+ }
});
- w.show();
- } else {
- Ext.Ajax.request({
- url : 'api/idnode/load',
- params : {
- uuid: r.id
- },
- success : function(d)
- {
- d = json_decode(d);
- var w = null;
- var c = { win: w };
- var p = tvheadend.idnode_editor(d[0], c);
- w = new Ext.Window({
- title : 'Edit ' + conf.titleS,
- layout : 'fit',
- autoWidth : true,
- autoHeight : true,
- plain : true,
- items : p
- });
- c.win = w;
- w.show();
- }
+ buttons.push(downBtn);
+ }
+ if (conf.add || conf.del || conf.move)
+ buttons.push('-');
+ editBtn = new Ext.Toolbar.Button({
+ tooltip: 'Edit selected entry',
+ iconCls: 'edit',
+ text: 'Edit',
+ disabled: true,
+ handler: function() {
+ var r = select.getSelected();
+ if (r) {
+ if (conf.edittree) {
+ var p = tvheadend.idnode_tree({
+ url: 'api/idnode/tree',
+ params: {
+ root: r.id
+ }
+ });
+ p.setSize(800, 600);
+ var w = new Ext.Window({
+ title: 'Edit ' + conf.titleS,
+ layout: 'fit',
+ autoWidth: true,
+ autoHeight: true,
+ plain: true,
+ items: p
+ });
+ w.show();
+ } else {
+ Ext.Ajax.request({
+ url: 'api/idnode/load',
+ params: {
+ uuid: r.id
+ },
+ success: function(d)
+ {
+ d = json_decode(d);
+ var w = null;
+ var c = {win: w};
+ var p = tvheadend.idnode_editor(d[0], c);
+ w = new Ext.Window({
+ title: 'Edit ' + conf.titleS,
+ layout: 'fit',
+ autoWidth: true,
+ autoHeight: true,
+ plain: true,
+ items: p
+ });
+ c.win = w;
+ w.show();
+ }
+ });
+ }
+ }
+ }
+ });
+ buttons.push(editBtn);
+
+ /* Hide Mode */
+ if (conf.hidemode) {
+ var hidemode = new Ext.form.ComboBox({
+ width: 100,
+ displayField: 'val',
+ valueField: 'key',
+ store: new Ext.data.ArrayStore({
+ id: 0,
+ fields: ['key', 'val'],
+ data: [['default', 'Parent disabled'],
+ ['all', 'All'],
+ ['none', 'None']]
+ }),
+ value: 'default',
+ mode: 'local',
+ forceSelection: false,
+ triggerAction: 'all',
+ listeners: {
+ select: function(s, r) {
+ store.baseParams.hidemode = r.id;
+ page.changePage(0);
+ store.reload();
+ }
+ }
});
- }
+ buttons.push('-');
+ buttons.push('Hide:');
+ buttons.push(hidemode);
}
- }
- });
- buttons.push(editBtn);
-
- /* Hide Mode */
- if (conf.hidemode) {
- var hidemode = new Ext.form.ComboBox({
- width : 100,
- displayField : 'val',
- valueField : 'key',
- store : new Ext.data.ArrayStore({
- id : 0,
- fields : [ 'key', 'val' ],
- data : [ ['default', 'Parent disabled'],
- ['all', 'All' ],
- ['none', 'None' ] ],
- }),
- value : 'default',
- mode : 'local',
- forceSelection : false,
- triggerAction : 'all',
- listeners : {
- select : function (s, r) {
- store.baseParams.hidemode = r.id;
- page.changePage(0);
- store.reload();
- }
+ var page = new Ext.PagingToolbar({
+ store: store,
+ pageSize: 50,
+ displayInfo: true,
+ displayMsg: conf.titleP + ' {0} - {1} of {2}',
+ width: 50
+ });
+
+ /* Extra buttons */
+ if (conf.tbar) {
+ buttons.push('-');
+ for (i = 0; i < conf.tbar.length; i++) {
+ if (conf.tbar[i].callback) {
+ conf.tbar[i].handler = function(b, e) {
+ this.callback(this, e, store, select);
+ };
+ }
+ buttons.push(conf.tbar[i]);
+ }
}
- });
- buttons.push('-');
- buttons.push('Hide:');
- buttons.push(hidemode);
- }
- var page = new Ext.PagingToolbar({
- store : store,
- pageSize : 50,
- displayInfo : true,
- displayMsg : conf.titleP + ' {0} - {1} of {2}',
- width : 50,
- });
- /* Extra buttons */
- if (conf.tbar) {
- buttons.push('-')
- for (i = 0; i < conf.tbar.length; i++) {
- if (conf.tbar[i].callback) {
- conf.tbar[i].handler = function (b, e) {
- this.callback(this, e, store, select);
- }
+ /* Help */
+ if (conf.help) {
+ buttons.push('->');
+ buttons.push({
+ text: 'Help',
+ handler: conf.help
+ });
}
- buttons.push(conf.tbar[i])
- }
+
+ /* Grid Panel */
+ var auto = new Ext.form.Checkbox({
+ checked: true,
+ listeners: {
+ check: function(s, c) {
+ if (c)
+ store.reload();
+ }
+ }
+ });
+ var count = new Ext.form.ComboBox({
+ width: 50,
+ displayField: 'val',
+ valueField: 'key',
+ store: new Ext.data.ArrayStore({
+ id: 0,
+ fields: ['key', 'val'],
+ data: [[25, '25'], [50, '50'], [100, '100'],
+ [200, '200'], [9999999999, 'All']]
+ }),
+ value: 50,
+ mode: 'local',
+ forceSelection: false,
+ triggerAction: 'all',
+ listeners: {
+ select: function(s, r) {
+ if (r !== page.pageSize) {
+ page.pageSize = r.id;
+ page.changePage(0);
+ store.reload();
+ // TODO: currently setting pageSize=-1 to disable paging confuses
+ // the UI elements, and I don't know how to sort that!
+ }
+ }
+ }
+ });
+ var page = new Ext.PagingToolbar({
+ store: store,
+ pageSize: 50,
+ displayInfo: true,
+ displayMsg: conf.titleP + ' {0} - {1} of {2}',
+ emptyMsg: 'No ' + conf.titleP.toLowerCase() + ' to display',
+ items: ['-', 'Auto-refresh', auto,
+ '->', '-', 'Per page', count]
+ });
+ plugins.push(filter);
+ var grid = new Ext.grid.EditorGridPanel({
+ stateful: true,
+ stateId: conf.url,
+ stripeRows: true,
+ title: conf.titleP,
+ store: store,
+ cm: model,
+ selModel: select,
+ plugins: plugins,
+ viewConfig: {
+ forceFit: true
+ },
+ tbar: buttons,
+ bbar: page
+ });
+ grid.on('filterupdate', function() {
+ page.changePage(0);
+ });
+
+ if (conf.tabIndex != null)
+ panel.insert(conf.tabIndex, grid);
+ else
+ panel.add(grid);
+
+ /* Add comet listeners */
+ var update = function(o) {
+ if (auto.getValue())
+ store.reload();
+ };
+ if (conf.comet)
+ tvheadend.comet.on(conf.comet, update);
+ tvheadend.comet.on('idnodeUpdated', update);
+ tvheadend.comet.on('idnodeDeleted', update);
}
- /* Help */
- if (conf.help) {
- buttons.push('->');
- buttons.push({
- text : 'Help',
- handler : conf.help
- });
+ /* Request data */
+ if (!conf.fields) {
+ Ext.Ajax.request({
+ url: conf.url + '/class',
+ success: function(d)
+ {
+ var d = json_decode(d);
+ build(d);
+ }
+ });
+ } else {
+ build(conf.fields);
}
+};
- /* Grid Panel */
- var auto = new Ext.form.Checkbox({
- checked : true,
- listeners : {
- check : function ( s, c ) {
- if (c) store.reload();
- }
- }
+tvheadend.idnode_tree = function(conf)
+{
+ var current = null;
+ var params = conf.params || {};
+ var loader = new Ext.tree.TreeLoader({
+ dataUrl: conf.url,
+ baseParams: params,
+ preloadChildren: conf.preload,
+ nodeParameter: 'uuid'
});
- var count = new Ext.form.ComboBox({
- width : 50,
- displayField : 'val',
- valueField : 'key',
- store : new Ext.data.ArrayStore({
- id : 0,
- fields : [ 'key', 'val' ],
- data : [[25, '25'], [50, '50'], [100, '100'],
- [200, '200'], [9999999999, 'All']]
- }),
- value : 50,
- mode : 'local',
- forceSelection : false,
- triggerAction : 'all',
- listeners : {
- select : function (s, r) {
- if (r != page.pageSize) {
- page.pageSize = r.id;
- page.changePage(0);
- store.reload();
- // TODO: currently setting pageSize=-1 to disable paging confuses
- // the UI elements, and I don't know how to sort that!
- }
+
+ var tree = new Ext.tree.TreePanel({
+ loader: loader,
+ flex: 1,
+ border: false,
+ animate: false,
+ root: new Ext.tree.AsyncTreeNode({
+ id: conf.root || 'root',
+ text: conf.title || ''
+ }),
+ listeners: {
+ click: function(n) {
+ if (current)
+ panel.remove(current);
+ if (!n.isRoot)
+ current = panel.add(new tvheadend.idnode_editor(n.attributes, {
+ title: 'Parameters',
+ fixedHeight: true,
+ help: conf.help || null
+ }));
+ panel.doLayout();
+ }
}
- }
- });
- var page = new Ext.PagingToolbar({
- store : store,
- pageSize : 50,
- displayInfo : true,
- displayMsg : conf.titleP + ' {0} - {1} of {2}',
- emptyMsg : 'No ' + conf.titleP.toLowerCase() + ' to display',
- items : [ '-', 'Auto-refresh', auto,
- '->', '-', 'Per page', count ]
- });
- plugins.push(filter);
- var grid = new Ext.grid.EditorGridPanel({
- stateful : true,
- stateId : conf.url,
- stripeRows : true,
- title : conf.titleP,
- store : store,
- cm : model,
- selModel : select,
- plugins : plugins,
- viewConfig : {
- forceFit : true
- },
- tbar : buttons,
- bbar : page
- });
- grid.on('filterupdate', function() {
- page.changePage(0);
});
- if (conf.tabIndex != null)
- panel.insert(conf.tabIndex, grid);
- else
- panel.add(grid);
+ if (conf.comet) {
+ tvheadend.comet.on(conf.comet, function(o) {
+ if (o.reload)
+ tree.getRootNode().reload();
+ });
+ }
- /* Add comet listeners */
- var update = function(o) {
- if (auto.getValue())
- store.reload();
- };
- if (conf.comet)
- tvheadend.comet.on(conf.comet, update);
- tvheadend.comet.on('idnodeUpdated', update);
- tvheadend.comet.on('idnodeDeleted', update);
- }
-
- /* Request data */
- if (!conf.fields) {
- Ext.Ajax.request({
- url : conf.url + '/class',
- success : function(d)
- {
- var d = json_decode(d);
- build(d);
- }
+ // TODO: top-level reload
+ tvheadend.comet.on('idnodeUpdated', function(o) {
+ var n = tree.getNodeById(o.uuid);
+ if (n) {
+ if (o.text)
+ n.setText(o.text);
+ tree.getRootNode().reload();
+ // cannot get this to properly reload children and maintain state
+ }
+ });
+
+ var panel = new Ext.Panel({
+ title: conf.title || '',
+ layout: 'hbox',
+ flex: 1,
+ padding: 5,
+ border: false,
+ layoutConfig: {
+ align: 'stretch'
+ },
+ items: [tree]
});
- } else {
- build(conf.fields);
- }
-}
-tvheadend.idnode_tree = function (conf)
-{
- var current = null;
- var params = conf.params || {};
- var loader = new Ext.tree.TreeLoader({
- dataUrl : conf.url,
- baseParams : params,
- preloadChildren : conf.preload,
- nodeParameter : 'uuid'
- });
-
- var tree = new Ext.tree.TreePanel({
- loader : loader,
- flex : 1,
- border : false,
- animate : false,
- root : new Ext.tree.AsyncTreeNode({
- id : conf.root || 'root',
- text : conf.title || ''
- }),
- listeners : {
- click: function(n) {
- if(current)
- panel.remove(current);
- if(!n.isRoot)
- current = panel.add(new tvheadend.idnode_editor(n.attributes, {
- title : 'Parameters',
- fixedHeight : true,
- help : conf.help || null,
- }));
- panel.doLayout();
- }
- }
- });
- if (conf.comet) {
- tvheadend.comet.on(conf.comet, function(o) {
- if (o.reload)
- tree.getRootNode().reload();
+ tree.on('beforerender', function() {
+ // To be honest this isn't quite right, but it'll do
+ tree.expandAll();
});
- }
-
- // TODO: top-level reload
- tvheadend.comet.on('idnodeUpdated', function(o) {
- var n = tree.getNodeById(o.uuid);
- if (n) {
- if (o.text) n.setText(o.text);
- tree.getRootNode().reload();
- // cannot get this to properly reload children and maintain state
- }
- });
-
- var panel = new Ext.Panel({
- title : conf.title || '',
- layout : 'hbox',
- flex : 1,
- padding : 5,
- border : false,
- layoutConfig : {
- align : 'stretch'
- },
- items: [ tree ]
- });
-
-
- tree.on('beforerender', function() {
- // To be honest this isn't quite right, but it'll do
- tree.expandAll();
- });
-
- return panel;
-}
+
+ return panel;
+};
*/
tvheadend.iptv = function(adapterId) {
- var servicetypeStore = new Ext.data.JsonStore({
- root : 'entries',
- id : 'val',
- url : '/iptv/services',
- baseParams : {
- op : 'servicetypeList'
- },
- fields : [ 'val', 'str' ],
- autoLoad : false,
- sortInfo : {
- field : 'channelname',
- direction : 'ASC'
- }
- });
+ var servicetypeStore = new Ext.data.JsonStore({
+ root: 'entries',
+ id: 'val',
+ url: '/iptv/services',
+ baseParams: {
+ op: 'servicetypeList'
+ },
+ fields: ['val', 'str'],
+ autoLoad: false,
+ sortInfo: {
+ field: 'channelname',
+ direction: 'ASC'
+ }
+ });
- var fm = Ext.form;
+ var fm = Ext.form;
- var actions = new Ext.ux.grid.RowActions({
- header : '',
- dataIndex : 'actions',
- width : 45,
- actions : [ {
- iconCls : 'info',
- qtip : 'Detailed information about service',
- cb : function(grid, record, action, row, col) {
- Ext.Ajax.request({
- url : "servicedetails/" + record.id,
- success : function(response, options) {
- r = Ext.util.JSON.decode(response.responseText);
- tvheadend.showTransportDetails(r);
- }
- })
- }
- } ]
- });
+ var actions = new Ext.ux.grid.RowActions({
+ header: '',
+ dataIndex: 'actions',
+ width: 45,
+ actions: [{
+ iconCls: 'info',
+ qtip: 'Detailed information about service',
+ cb: function(grid, record, action, row, col) {
+ Ext.Ajax.request({
+ url: "servicedetails/" + record.id,
+ success: function(response, options) {
+ r = Ext.util.JSON.decode(response.responseText);
+ tvheadend.showTransportDetails(r);
+ }
+ });
+ }
+ }]
+ });
- var cm = new Ext.grid.ColumnModel({
- defaultSortable: true,
- columns : [
- {
- xtype: 'checkcolumn',
- header : "Enabled",
- dataIndex : 'enabled',
- width : 45
- },
- {
- header : "Channel name",
- dataIndex : 'channelname',
- width : 150,
- renderer : function(value, metadata, record, row, col, store) {
- return value ? value
- : '<span class="tvh-grid-unset">Unmapped</span>';
- },
- editor : new fm.ComboBox({
- store : tvheadend.channels,
- allowBlank : true,
- typeAhead : true,
- minChars : 2,
- lazyRender : true,
- triggerAction : 'all',
- mode : 'local',
- displayField : 'name'
- })
- },
- {
- header : "Interface",
- dataIndex : 'interface',
- width : 100,
- renderer : function(value, metadata, record, row, col, store) {
- return value ? value : '<span class="tvh-grid-unset">Unset</span>';
- },
- editor : new fm.TextField({
- allowBlank : false
- })
- },
- {
- header : "Group",
- dataIndex : 'group',
- width : 100,
- renderer : function(value, metadata, record, row, col, store) {
- return value ? value : '<span class="tvh-grid-unset">Unset</span>';
- },
- editor : new fm.TextField({
- allowBlank : false
- })
- },
- {
- header : "UDP Port",
- dataIndex : 'port',
- width : 60,
- editor : new fm.NumberField({
- minValue : 1,
- maxValue : 65535
- })
- },
- {
- header : "Service ID",
- dataIndex : 'sid',
- width : 50,
- hidden : true
- },
- {
- header : 'Service Type',
- width : 100,
- dataIndex : 'stype',
- hidden : true,
- editor : new fm.ComboBox({
- valueField : 'val',
- displayField : 'str',
- forceSelection : false,
- editable : false,
- mode : 'local',
- triggerAction : 'all',
- store : servicetypeStore
- }),
- renderer : function(value, metadata, record, row, col, store) {
- var val = value ? servicetypeStore.getById(value) : null;
- return val ? val.get('str')
- : '<span class="tvh-grid-unset">Unset</span>';
- }
- }, {
- header : "PMT PID",
- dataIndex : 'pmt',
- width : 50,
- hidden : true
- }, {
- header : "PCR PID",
- dataIndex : 'pcr',
- width : 50,
- hidden : true
- }, actions ]});
+ var cm = new Ext.grid.ColumnModel({
+ defaultSortable: true,
+ columns: [
+ {
+ xtype: 'checkcolumn',
+ header: "Enabled",
+ dataIndex: 'enabled',
+ width: 45
+ },
+ {
+ header: "Channel name",
+ dataIndex: 'channelname',
+ width: 150,
+ renderer: function(value, metadata, record, row, col, store) {
+ return value ? value
+ : '<span class="tvh-grid-unset">Unmapped</span>';
+ },
+ editor: new fm.ComboBox({
+ store: tvheadend.channels,
+ allowBlank: true,
+ typeAhead: true,
+ minChars: 2,
+ lazyRender: true,
+ triggerAction: 'all',
+ mode: 'local',
+ displayField: 'name'
+ })
+ },
+ {
+ header: "Interface",
+ dataIndex: 'interface',
+ width: 100,
+ renderer: function(value, metadata, record, row, col, store) {
+ return value ? value : '<span class="tvh-grid-unset">Unset</span>';
+ },
+ editor: new fm.TextField({
+ allowBlank: false
+ })
+ },
+ {
+ header: "Group",
+ dataIndex: 'group',
+ width: 100,
+ renderer: function(value, metadata, record, row, col, store) {
+ return value ? value : '<span class="tvh-grid-unset">Unset</span>';
+ },
+ editor: new fm.TextField({
+ allowBlank: false
+ })
+ },
+ {
+ header: "UDP Port",
+ dataIndex: 'port',
+ width: 60,
+ editor: new fm.NumberField({
+ minValue: 1,
+ maxValue: 65535
+ })
+ },
+ {
+ header: "Service ID",
+ dataIndex: 'sid',
+ width: 50,
+ hidden: true
+ },
+ {
+ header: 'Service Type',
+ width: 100,
+ dataIndex: 'stype',
+ hidden: true,
+ editor: new fm.ComboBox({
+ valueField: 'val',
+ displayField: 'str',
+ forceSelection: false,
+ editable: false,
+ mode: 'local',
+ triggerAction: 'all',
+ store: servicetypeStore
+ }),
+ renderer: function(value, metadata, record, row, col, store) {
+ var val = value ? servicetypeStore.getById(value) : null;
+ return val ? val.get('str')
+ : '<span class="tvh-grid-unset">Unset</span>';
+ }
+ }, {
+ header: "PMT PID",
+ dataIndex: 'pmt',
+ width: 50,
+ hidden: true
+ }, {
+ header: "PCR PID",
+ dataIndex: 'pcr',
+ width: 50,
+ hidden: true
+ }, actions]});
- var rec = Ext.data.Record.create([ 'id', 'enabled', 'channelname',
- 'interface', 'group', 'port', 'sid', 'pmt', 'pcr', 'stype' ]);
+ var rec = Ext.data.Record.create(['id', 'enabled', 'channelname',
+ 'interface', 'group', 'port', 'sid', 'pmt', 'pcr', 'stype']);
- var store = new Ext.data.JsonStore({
- root : 'entries',
- fields : rec,
- url : "iptv/services",
- autoLoad : true,
- id : 'id',
- baseParams : {
- op : "get"
- },
- listeners : {
- 'update' : function(s, r, o) {
- d = s.getModifiedRecords().length == 0
- saveBtn.setDisabled(d);
- rejectBtn.setDisabled(d);
- }
- }
- });
+ var store = new Ext.data.JsonStore({
+ root: 'entries',
+ fields: rec,
+ url: "iptv/services",
+ autoLoad: true,
+ id: 'id',
+ baseParams: {
+ op: "get"
+ },
+ listeners: {
+ 'update': function(s, r, o) {
+ d = s.getModifiedRecords().length === 0
+ saveBtn.setDisabled(d);
+ rejectBtn.setDisabled(d);
+ }
+ }
+ });
- /*
- var storeReloader = new Ext.util.DelayedTask(function() {
- store.reload()
- });
+ /*
+ var storeReloader = new Ext.util.DelayedTask(function() {
+ store.reload()
+ });
+
+ tvheadend.comet.on('dvbService', function(m) {
+ storeReloader.delay(500);
+ });
+ */
- tvheadend.comet.on('dvbService', function(m) {
- storeReloader.delay(500);
- });
- */
+ function addRecord() {
+ Ext.Ajax.request({
+ url: "iptv/services",
+ params: {
+ op: "create"
+ },
+ failure: function(response, options) {
+ Ext.MessageBox.alert('Server Error',
+ 'Unable to generate new record');
+ },
+ success: function(response, options) {
+ var responseData = Ext.util.JSON.decode(response.responseText);
+ var p = new rec(responseData, responseData.id);
+ grid.stopEditing();
+ store.insert(0, p);
+ grid.startEditing(0, 0);
+ }
+ });
+ }
+ ;
- function addRecord() {
- Ext.Ajax.request({
- url : "iptv/services",
- params : {
- op : "create"
- },
- failure : function(response, options) {
- Ext.MessageBox.alert('Server Error',
- 'Unable to generate new record');
- },
- success : function(response, options) {
- var responseData = Ext.util.JSON.decode(response.responseText);
- var p = new rec(responseData, responseData.id);
- grid.stopEditing();
- store.insert(0, p);
- grid.startEditing(0, 0);
- }
- })
- }
- ;
+ function delSelected() {
+ var selectedKeys = grid.selModel.selections.keys;
+ if (selectedKeys.length > 0) {
+ Ext.MessageBox.confirm('Message',
+ 'Do you really want to delete selection?', deleteRecord);
+ }
+ else {
+ Ext.MessageBox.alert('Message',
+ 'Please select at least one item to delete');
+ }
+ }
+ ;
- function delSelected() {
- var selectedKeys = grid.selModel.selections.keys;
- if (selectedKeys.length > 0) {
- Ext.MessageBox.confirm('Message',
- 'Do you really want to delete selection?', deleteRecord);
- }
- else {
- Ext.MessageBox.alert('Message',
- 'Please select at least one item to delete');
- }
- }
- ;
+ function deleteRecord(btn) {
+ if (btn === 'yes') {
+ var selectedKeys = grid.selModel.selections.keys;
- function deleteRecord(btn) {
- if (btn == 'yes') {
- var selectedKeys = grid.selModel.selections.keys;
+ Ext.Ajax.request({
+ url: "iptv/services",
+ params: {
+ op: "delete",
+ entries: Ext.encode(selectedKeys)
+ },
+ failure: function(response, options) {
+ Ext.MessageBox.alert('Server Error', 'Unable to delete');
+ },
+ success: function(response, options) {
+ store.reload();
+ }
+ });
+ }
+ }
- Ext.Ajax.request({
- url : "iptv/services",
- params : {
- op : "delete",
- entries : Ext.encode(selectedKeys)
- },
- failure : function(response, options) {
- Ext.MessageBox.alert('Server Error', 'Unable to delete');
- },
- success : function(response, options) {
- store.reload();
- }
- })
- }
- }
+ function saveChanges() {
+ var mr = store.getModifiedRecords();
+ var out = new Array();
+ for (var x = 0; x < mr.length; x++) {
+ v = mr[x].getChanges();
+ out[x] = v;
+ out[x].id = mr[x].id;
+ }
- function saveChanges() {
- var mr = store.getModifiedRecords();
- var out = new Array();
- for ( var x = 0; x < mr.length; x++) {
- v = mr[x].getChanges();
- out[x] = v;
- out[x].id = mr[x].id;
- }
+ Ext.Ajax.request({
+ url: "iptv/services",
+ params: {
+ op: "update",
+ entries: Ext.encode(out)
+ },
+ success: function(response, options) {
+ store.commitChanges();
+ },
+ failure: function(response, options) {
+ Ext.MessageBox.alert('Message', response.statusText);
+ }
+ });
+ }
- Ext.Ajax.request({
- url : "iptv/services",
- params : {
- op : "update",
- entries : Ext.encode(out)
- },
- success : function(response, options) {
- store.commitChanges();
- },
- failure : function(response, options) {
- Ext.MessageBox.alert('Message', response.statusText);
- }
- });
- }
+ var delButton = new Ext.Toolbar.Button({
+ tooltip: 'Delete one or more selected rows',
+ iconCls: 'remove',
+ text: 'Delete selected services',
+ handler: delSelected,
+ disabled: true
+ });
- var delButton = new Ext.Toolbar.Button({
- tooltip : 'Delete one or more selected rows',
- iconCls : 'remove',
- text : 'Delete selected services',
- handler : delSelected,
- disabled : true
- });
+ var saveBtn = new Ext.Toolbar.Button({
+ tooltip: 'Save any changes made (Changed cells have red borders).',
+ iconCls: 'save',
+ text: "Save changes",
+ handler: saveChanges,
+ disabled: true
+ });
- var saveBtn = new Ext.Toolbar.Button({
- tooltip : 'Save any changes made (Changed cells have red borders).',
- iconCls : 'save',
- text : "Save changes",
- handler : saveChanges,
- disabled : true
- });
+ var rejectBtn = new Ext.Toolbar.Button({
+ tooltip: 'Revert any changes made (Changed cells have red borders).',
+ iconCls: 'undo',
+ text: "Revert changes",
+ handler: function() {
+ store.rejectChanges();
+ },
+ disabled: true
+ });
- var rejectBtn = new Ext.Toolbar.Button({
- tooltip : 'Revert any changes made (Changed cells have red borders).',
- iconCls : 'undo',
- text : "Revert changes",
- handler : function() {
- store.rejectChanges();
- },
- disabled : true
- });
+ var selModel = new Ext.grid.RowSelectionModel({
+ singleSelect: false
+ });
- var selModel = new Ext.grid.RowSelectionModel({
- singleSelect : false
- });
+ var grid = new Ext.grid.EditorGridPanel({
+ stripeRows: true,
+ title: 'IPTV',
+ iconCls: 'iptv',
+ plugins: [actions],
+ store: store,
+ clicksToEdit: 2,
+ cm: cm,
+ viewConfig: {
+ forceFit: true
+ },
+ selModel: selModel,
+ tbar: [
+ {
+ tooltip: 'Create a new entry on the server. '
+ + 'The new entry is initially disabled so it must be enabled '
+ + 'before it start taking effect.',
+ iconCls: 'add',
+ text: 'Add service',
+ handler: addRecord
+ }, '-', delButton, '-', saveBtn, rejectBtn, '->',
+ {
+ text: 'Help',
+ handler: function() {
+ new tvheadend.help('IPTV', 'config_iptv.html');
+ }
+ }]
+ });
- var grid = new Ext.grid.EditorGridPanel({
- stripeRows : true,
- title : 'IPTV',
- iconCls : 'iptv',
- plugins : [ actions ],
- store : store,
- clicksToEdit : 2,
- cm : cm,
- viewConfig : {
- forceFit : true
- },
- selModel : selModel,
- tbar : [
- {
- tooltip : 'Create a new entry on the server. '
- + 'The new entry is initially disabled so it must be enabled '
- + 'before it start taking effect.',
- iconCls : 'add',
- text : 'Add service',
- handler : addRecord
- }, '-', delButton, '-', saveBtn, rejectBtn, '->',
- {
- text : 'Help',
- handler : function() {
- new tvheadend.help('IPTV', 'config_iptv.html');
- }
- } ]
- });
+ store.on('update', function(s, r, o) {
+ d = s.getModifiedRecords().length === 0;
+ saveBtn.setDisabled(d);
+ rejectBtn.setDisabled(d);
+ });
- store.on('update', function(s, r, o) {
- d = s.getModifiedRecords().length == 0
- saveBtn.setDisabled(d);
- rejectBtn.setDisabled(d);
- });
+ selModel.on('selectionchange', function(self) {
+ delButton.setDisabled(self.getCount() === 0);
+ });
- selModel.on('selectionchange', function(self) {
- delButton.setDisabled(self.getCount() == 0);
- });
-
- return grid;
-}
+ return grid;
+};
*/
tvheadend.network_builders = new Ext.data.JsonStore({
- url : 'api/mpegts/network/builders',
- root : 'entries',
- fields : [ 'class', 'caption', 'props' ],
- id : 'class',
- autoLoad : true,
+ url: 'api/mpegts/network/builders',
+ root: 'entries',
+ fields: ['class', 'caption', 'props'],
+ id: 'class',
+ autoLoad: true
});
tvheadend.network_list = new Ext.data.JsonStore({
- url : 'api/idnode/load',
- baseParams : { class : 'mpegts_network', enum: 1 },
- root : 'entries',
- fields : [ 'key', 'val' ],
- id : 'key',
- autoLoad : true,
+ url: 'api/idnode/load',
+ baseParams: {class: 'mpegts_network', enum: 1},
+ root: 'entries',
+ fields: ['key', 'val'],
+ id: 'key',
+ autoLoad: true
});
tvheadend.comet.on('mpegts_network', function() {
- // TODO: Might be a bit excessive
- tvheadend.network_builders.reload();
- tvheadend.network_list.reload();
+ // TODO: Might be a bit excessive
+ tvheadend.network_builders.reload();
+ tvheadend.network_list.reload();
});
tvheadend.networks = function(panel)
{
- tvheadend.idnode_grid(panel, {
- url : 'api/mpegts/network',
- comet : 'mpegts_network',
- titleS : 'Network',
- titleP : 'Networks',
- tabIndex : 1,
- add : {
- titleS : 'Network',
- select : {
- label : 'Type',
- store : tvheadend.network_builders,
- displayField : 'caption',
- valueField : 'class',
- propField : 'props',
- },
- create : {
- url : 'api/mpegts/network/create'
- }
- },
- del : true,
- sort : {
- field : 'networkname',
- direction : 'ASC'
- }
- });
-}
+ tvheadend.idnode_grid(panel, {
+ url: 'api/mpegts/network',
+ comet: 'mpegts_network',
+ titleS: 'Network',
+ titleP: 'Networks',
+ tabIndex: 1,
+ add: {
+ titleS: 'Network',
+ select: {
+ label: 'Type',
+ store: tvheadend.network_builders,
+ displayField: 'caption',
+ valueField: 'class',
+ propField: 'props'
+ },
+ create: {
+ url: 'api/mpegts/network/create'
+ }
+ },
+ del: true,
+ sort: {
+ field: 'networkname',
+ direction: 'ASC'
+ }
+ });
+};
tvheadend.muxes = function(panel)
{
- tvheadend.idnode_grid(panel, {
- url : 'api/mpegts/mux',
- comet : 'mpegts_mux',
- titleS : 'Mux',
- titleP : 'Muxes',
- tabIndex : 2,
- hidemode : true,
- add : {
- titleS : 'Mux',
- select : {
- label : 'Network',
- store : tvheadend.network_list,
- valueField : 'key',
- displayField : 'val',
- clazz : {
- url : 'api/mpegts/network/mux_class'
+ tvheadend.idnode_grid(panel, {
+ url: 'api/mpegts/mux',
+ comet: 'mpegts_mux',
+ titleS: 'Mux',
+ titleP: 'Muxes',
+ tabIndex: 2,
+ hidemode: true,
+ add: {
+ titleS: 'Mux',
+ select: {
+ label: 'Network',
+ store: tvheadend.network_list,
+ valueField: 'key',
+ displayField: 'val',
+ clazz: {
+ url: 'api/mpegts/network/mux_class'
+ }
+ },
+ create: {
+ url: 'api/mpegts/network/mux_create'
+ }
+ },
+ del: true,
+ lcol: [
+ {
+ width: 50,
+ header: 'Play',
+ renderer: function(v, o, r) {
+ return "<a href='stream/mux/" + r.id + "'>Play</a>";
+ }
+ }
+ ],
+ sort: {
+ field: 'name',
+ direction: 'ASC'
}
- },
- create : {
- url : 'api/mpegts/network/mux_create',
- }
- },
- del : true,
- lcol : [
- {
- width : 50,
- header : 'Play',
- renderer : function(v, o, r) {
- return "<a href='stream/mux/" + r.id + "'>Play</a>";
- }
- }
- ],
- sort : {
- field : 'name',
- direction : 'ASC'
+ });
+};
+
+tvheadend.show_service_streams = function(data) {
+ var i, j;
+ var html = '';
+
+ function hexstr(d) {
+ return ('0000' + d.toString(16)).slice(-4);
}
- });
-}
-tvheadend.show_service_streams = function ( data ) {
- var i, j;
- var html = '';
+ function hexstr6(d) {
+ return ('000000' + d.toString(16)).slice(-6);
+ }
- function hexstr ( d ) {
- return ('0000' + d.toString(16)).slice(-4);
- }
-
- function hexstr6 ( d ) {
- return ('000000' + d.toString(16)).slice(-6);
- }
-
- function fixstr ( d ) {
- var r = d.toString();
- var l = r.length;
- var i;
- for (i = l; i < 5; i++) {
- r = ' ' + r;
+ function fixstr(d) {
+ var r = d.toString();
+ var l = r.length;
+ var i;
+ for (i = l; i < 5; i++) {
+ r = ' ' + r;
+ }
+ return r;
}
- return r;
- }
- function header ( ) {
- html += '<table style="font-size:8pt;font-family:mono;padding:2px"';
- html += '<tr>';
- html += '<th style="width:50px;font-weight:bold">Index</th>';
- html += '<th style="width:120px;font-weight:bold">PID</th>';
- html += '<th style="width:100px;font-weight:bold">Type</th>';
- html += '<th style="width:75px;font-weight:bold">Language</th>';
- html += '<th style="width:*;font-weight:bold">Details</th>';
- html += '</tr>';
+ function header( ) {
+ html += '<table style="font-size:8pt;font-family:mono;padding:2px"';
+ html += '<tr>';
+ html += '<th style="width:50px;font-weight:bold">Index</th>';
+ html += '<th style="width:120px;font-weight:bold">PID</th>';
+ html += '<th style="width:100px;font-weight:bold">Type</th>';
+ html += '<th style="width:75px;font-weight:bold">Language</th>';
+ html += '<th style="width:*;font-weight:bold">Details</th>';
+ html += '</tr>';
- }
+ }
- function single ( s ) {
- html += '<tr><td colspan="5">' + s + '</td></tr>';
- }
+ function single(s) {
+ html += '<tr><td colspan="5">' + s + '</td></tr>';
+ }
- function stream ( s ) {
- var d = ' ';
- var p = '0x' + hexstr(s.pid) + ' / ' + fixstr(s.pid);
+ function stream(s) {
+ var d = ' ';
+ var p = '0x' + hexstr(s.pid) + ' / ' + fixstr(s.pid);
- html += '<tr>';
- html += '<td>' + (s.index > 0 ? s.index : ' ') + '</td>';
- html += '<td>' + p + '</td>';
- html += '<td>' + s.type + '</td>';
- html += '<td>' + (s.language || ' ') + '</td>'
- if (s.type == 'CA') {
- d = 'CAIDS: ';
- for (j = 0; j < s.caids.length; j++) {
- if (j > 0) d += ', ';
- d += hexstr(s.caids[j].caid) + ':';
- d += hexstr6(s.caids[j].provider);
- }
+ html += '<tr>';
+ html += '<td>' + (s.index > 0 ? s.index : ' ') + '</td>';
+ html += '<td>' + p + '</td>';
+ html += '<td>' + s.type + '</td>';
+ html += '<td>' + (s.language || ' ') + '</td>';
+ if (s.type === 'CA') {
+ d = 'CAIDS: ';
+ for (j = 0; j < s.caids.length; j++) {
+ if (j > 0)
+ d += ', ';
+ d += hexstr(s.caids[j].caid) + ':';
+ d += hexstr6(s.caids[j].provider);
+ }
+ }
+ html += '<td>' + d + '</td>';
+ html += '</tr>';
}
- html += '<td>' + d + '</td>';
- html += '</tr>';
- }
- header();
+ header();
- if (data.streams.length) {
- for (i = 0; i < data.streams.length; i++)
- stream(data.streams[i]);
- } else
- single('None');
+ if (data.streams.length) {
+ for (i = 0; i < data.streams.length; i++)
+ stream(data.streams[i]);
+ } else
+ single('None');
- single(' ');
- single('<h3>After filtering and reordering (without PCR and PMT)</h3>');
- header();
+ single(' ');
+ single('<h3>After filtering and reordering (without PCR and PMT)</h3>');
+ header();
- if (data.fstreams.length)
- for (i = 0; i < data.fstreams.length; i++)
- stream(data.fstreams[i]);
- else
- single('<p>None</p>');
+ if (data.fstreams.length)
+ for (i = 0; i < data.fstreams.length; i++)
+ stream(data.fstreams[i]);
+ else
+ single('<p>None</p>');
- var win = new Ext.Window({
- title : 'Service details for ' + data.name,
- layout : 'fit',
- width : 650,
- height : 400,
- plain : true,
- bodyStyle : 'padding: 5px',
- html : html,
- autoScroll: true,
- autoShow: true
- });
- win.show();
-}
+ var win = new Ext.Window({
+ title: 'Service details for ' + data.name,
+ layout: 'fit',
+ width: 650,
+ height: 400,
+ plain: true,
+ bodyStyle: 'padding: 5px',
+ html: html,
+ autoScroll: true,
+ autoShow: true
+ });
+ win.show();
+};
tvheadend.services = function(panel)
{
- var mapButton = new Ext.Toolbar.Button({
- tooltip : 'Map services to channels',
- iconCls : 'clone',
- text : 'Map All',
- callback : tvheadend.service_mapper,
- disabled : false,
- });
- var selected = function (s)
- {
- if (s.getCount() > 0)
- mapButton.setText('Map Selected')
- else
- mapButton.setText('Map All')
- }
- var actions = new Ext.ux.grid.RowActions({
- header : '',
- width : 10,
- actions : [ {
- iconCls : 'info',
- qtip : 'Detailed stream info',
- cb : function ( grid, rec, act, row, col ) {
- Ext.Ajax.request({
- url : 'api/service/streams',
- params : {
- uuid : rec.id
- },
- success : function (r, o) {
- var d = Ext.util.JSON.decode(r.responseText);
- tvheadend.show_service_streams(d);
- }
- });
- }
- } ]
- });
- tvheadend.idnode_grid(panel, {
- url : 'api/mpegts/service',
- comet : 'service',
- titleS : 'Service',
- titleP : 'Services',
- tabIndex : 3,
- hidemode : true,
- add : false,
- del : false,
- selected : selected,
- tbar : [ mapButton ],
- lcol : [
- {
- width : 50,
- header : 'Play',
- renderer : function(v, o, r) {
- return "<a href='stream/service/" + r.id + "'>Play</a>";
+ var mapButton = new Ext.Toolbar.Button({
+ tooltip: 'Map services to channels',
+ iconCls: 'clone',
+ text: 'Map All',
+ callback: tvheadend.service_mapper,
+ disabled: false
+ });
+ var selected = function(s)
+ {
+ if (s.getCount() > 0)
+ mapButton.setText('Map Selected');
+ else
+ mapButton.setText('Map All');
+ };
+ var actions = new Ext.ux.grid.RowActions({
+ header: '',
+ width: 10,
+ actions: [{
+ iconCls: 'info',
+ qtip: 'Detailed stream info',
+ cb: function(grid, rec, act, row, col) {
+ Ext.Ajax.request({
+ url: 'api/service/streams',
+ params: {
+ uuid: rec.id
+ },
+ success: function(r, o) {
+ var d = Ext.util.JSON.decode(r.responseText);
+ tvheadend.show_service_streams(d);
+ }
+ });
+ }
+ }]
+ });
+ tvheadend.idnode_grid(panel, {
+ url: 'api/mpegts/service',
+ comet: 'service',
+ titleS: 'Service',
+ titleP: 'Services',
+ tabIndex: 3,
+ hidemode: true,
+ add: false,
+ del: false,
+ selected: selected,
+ tbar: [mapButton],
+ lcol: [
+ {
+ width: 50,
+ header: 'Play',
+ renderer: function(v, o, r) {
+ return "<a href='stream/service/" + r.id + "'>Play</a>";
+ }
+ },
+ actions
+ ],
+ plugins: [actions],
+ sort: {
+ field: 'svcname',
+ direction: 'ASC'
}
- },
- actions
- ],
- plugins : [ actions ],
- sort : {
- field : 'svcname',
- direction : 'ASC'
- }
- });
-}
+ });
+};
tvheadend.mux_sched = function(panel)
{
- tvheadend.idnode_grid(panel, {
- url : 'api/mpegts/mux_sched',
- comet : 'mpegts_mux_sched',
- titleS : 'Mux Scheduler',
- titleP : 'Mux Schedulers',
- tabIndex : 4,
- hidemode : true,
- add : {
- url : 'api/mpegts/mux_sched',
- titleS : 'Mux Scheduler',
- create : {
- url : 'api/mpegts/mux_sched/create'
- }
- },
- del : true
- });
-}
+ tvheadend.idnode_grid(panel, {
+ url: 'api/mpegts/mux_sched',
+ comet: 'mpegts_mux_sched',
+ titleS: 'Mux Scheduler',
+ titleP: 'Mux Schedulers',
+ tabIndex: 4,
+ hidemode: true,
+ add: {
+ url: 'api/mpegts/mux_sched',
+ titleS: 'Mux Scheduler',
+ create: {
+ url: 'api/mpegts/mux_sched/create'
+ }
+ },
+ del: true
+ });
+};
tvheadend.service_mapper_status_panel = null;
-tvheadend.service_mapper_status = function ()
+tvheadend.service_mapper_status = function()
{
- var panel;
-
- /* Fields */
- var ok = new Ext.form.Label({
- fieldLabel : 'Mapped',
- text : '0'
- });
- var fail = new Ext.form.Label({
- fieldLabel : 'Failed',
- text : '0'
- });
- var ignore = new Ext.form.Label({
- fieldLabel : 'Ignored',
- text : '0'
- });
- var active = new Ext.form.Label({
- width : 200,
- fieldLabel : 'Active',
- text : ''
- });
- var prog = new Ext.ProgressBar({
- text : '0 / 0'
- });
-
- /* Panel */
- panel = new Ext.FormPanel({
- method : 'get',
- title : 'Service Mapper',
- frame : true,
- border : true,
- bodyStyle : 'padding: 5px',
- labelAlign : 'left',
- labelWidth : 200,
- width : 400,
- autoHeight : true,
- defaultType : 'textfield',
- buttonAlign : 'left',
- items : [ ok, ignore, fail, active, prog ]
- });
-
- /* Comet */
- tvheadend.comet.on('servicemapper', function(m) {
- var n = m.ok + m.ignore + m.fail;
- ok.setText('' + m.ok);
- ignore.setText('' + m.ignore);
- fail.setText('' + m.fail);
- active.setText('');
- prog.updateProgress(n / m.total, '' + n + ' / ' + m.total);
-
- if (m.active) {
- Ext.Ajax.request({
- url : 'api/idnode/load',
- params : {
- uuid : m.active
- },
- success : function (d) {
- d = Ext.util.JSON.decode(d.responseText);
- try {
- active.setText(d.entries[0].text);
- } catch (e) {
- }
+ var panel;
+
+ /* Fields */
+ var ok = new Ext.form.Label({
+ fieldLabel: 'Mapped',
+ text: '0'
+ });
+ var fail = new Ext.form.Label({
+ fieldLabel: 'Failed',
+ text: '0'
+ });
+ var ignore = new Ext.form.Label({
+ fieldLabel: 'Ignored',
+ text: '0'
+ });
+ var active = new Ext.form.Label({
+ width: 200,
+ fieldLabel: 'Active',
+ text: ''
+ });
+ var prog = new Ext.ProgressBar({
+ text: '0 / 0'
+ });
+
+ /* Panel */
+ panel = new Ext.FormPanel({
+ method: 'get',
+ title: 'Service Mapper',
+ frame: true,
+ border: true,
+ bodyStyle: 'padding: 5px',
+ labelAlign: 'left',
+ labelWidth: 200,
+ width: 400,
+ autoHeight: true,
+ defaultType: 'textfield',
+ buttonAlign: 'left',
+ items: [ok, ignore, fail, active, prog]
+ });
+
+ /* Comet */
+ tvheadend.comet.on('servicemapper', function(m) {
+ var n = m.ok + m.ignore + m.fail;
+ ok.setText('' + m.ok);
+ ignore.setText('' + m.ignore);
+ fail.setText('' + m.fail);
+ active.setText('');
+ prog.updateProgress(n / m.total, '' + n + ' / ' + m.total);
+
+ if (m.active) {
+ Ext.Ajax.request({
+ url: 'api/idnode/load',
+ params: {
+ uuid: m.active
+ },
+ success: function(d) {
+ d = Ext.util.JSON.decode(d.responseText);
+ try {
+ active.setText(d.entries[0].text);
+ } catch (e) {
+ }
+ }
+ });
}
- });
- }
- });
+ });
- tvheadend.service_mapper_status_panel = panel;
- return panel;
-}
+ tvheadend.service_mapper_status_panel = panel;
+ return panel;
+};
/*
* Start mapping
*/
tvheadend.service_mapper = function(t, e, store, select)
{
- var panel = null;
- var win = null;
-
- /* Form fields */
- var availCheck = new Ext.form.Checkbox({
- name : 'check_availability',
- fieldLabel : 'Check availability',
- checked : false
- });
- var ftaCheck = new Ext.form.Checkbox({
- name : 'encrypted',
- fieldLabel : 'Include encrypted services',
- checked : false,
- // TODO: make dependent on CSA config
- });
- var mergeCheck = new Ext.form.Checkbox({
- name : 'merge_same_name',
- fieldLabel : 'Merge same name',
- checked : false
- });
- var provtagCheck = new Ext.form.Checkbox({
- name : 'provider_tags',
- fieldLabel : 'Create provider tags',
- checked : false
- });
-
- // TODO: provider list
- items = [ availCheck, ftaCheck, mergeCheck, provtagCheck ];
-
- /* Form */
- var undoBtn = new Ext.Button({
- text : 'Cancel',
- handler : function () {
- win.close();
- }
- });
-
- var saveBtn = new Ext.Button({
- text : 'Map',
- tooltip : 'Begin mapping',
- handler : function () {
- p = null;
- if (select) {
- var r = select.getSelections();
- if (r.length > 0) {
- var uuids = [];
- for (var i = 0; i < r.length; i++)
- uuids.push(r[i].id);
- p = { uuids: Ext.encode(uuids) };
+ var panel = null;
+ var win = null;
+
+ /* Form fields */
+ var availCheck = new Ext.form.Checkbox({
+ name: 'check_availability',
+ fieldLabel: 'Check availability',
+ checked: false
+ });
+ var ftaCheck = new Ext.form.Checkbox({
+ name: 'encrypted',
+ fieldLabel: 'Include encrypted services',
+ checked: false
+ // TODO: make dependent on CSA config
+ });
+ var mergeCheck = new Ext.form.Checkbox({
+ name: 'merge_same_name',
+ fieldLabel: 'Merge same name',
+ checked: false
+ });
+ var provtagCheck = new Ext.form.Checkbox({
+ name: 'provider_tags',
+ fieldLabel: 'Create provider tags',
+ checked: false
+ });
+
+ // TODO: provider list
+ items = [availCheck, ftaCheck, mergeCheck, provtagCheck];
+
+ /* Form */
+ var undoBtn = new Ext.Button({
+ text: 'Cancel',
+ handler: function() {
+ win.close();
}
- }
-
-
- panel.getForm().submit({
- url : 'api/service/mapper/start',
- waitMessage : 'Mapping services...',
- params : p
- });
-
- win.hide();
-
- /* Dialog */
- win = new Ext.Window({
- title : 'Service Mapper Status',
- layout : 'fit',
- autoWidth : true,
- autoHeight : true,
- plain : false,
- items : tvheadend.service_mapper_status_panel
- // TODO: buttons
- });
- win.show();
- }
- });
-
- panel = new Ext.FormPanel({
- method : 'post',
- frame : true,
- border : true,
- bodyStyle : 'padding: 5px',
- labelAlign : 'left',
- labelWidth : 200,
- autoWidth : true,
- autoHeight : true,
- defaultType : 'textfield',
- buttonAlign : 'left',
- items : items,
- buttons : [ undoBtn, saveBtn ]
- });
-
- /* Create window */
- win = new Ext.Window({
- title : 'Map services',
- layout : 'fit',
- autoWidth : true,
- autoHeight : true,
- plain : true,
- items : panel
- });
-
- win.show();
-}
+ });
+
+ var saveBtn = new Ext.Button({
+ text: 'Map',
+ tooltip: 'Begin mapping',
+ handler: function() {
+ p = null;
+ if (select) {
+ var r = select.getSelections();
+ if (r.length > 0) {
+ var uuids = [];
+ for (var i = 0; i < r.length; i++)
+ uuids.push(r[i].id);
+ p = {uuids: Ext.encode(uuids)};
+ }
+ }
+
+
+ panel.getForm().submit({
+ url: 'api/service/mapper/start',
+ waitMessage: 'Mapping services...',
+ params: p
+ });
+
+ win.hide();
+
+ /* Dialog */
+ win = new Ext.Window({
+ title: 'Service Mapper Status',
+ layout: 'fit',
+ autoWidth: true,
+ autoHeight: true,
+ plain: false,
+ items: tvheadend.service_mapper_status_panel
+ // TODO: buttons
+ });
+ win.show();
+ }
+ });
+
+ panel = new Ext.FormPanel({
+ method: 'post',
+ frame: true,
+ border: true,
+ bodyStyle: 'padding: 5px',
+ labelAlign: 'left',
+ labelWidth: 200,
+ autoWidth: true,
+ autoHeight: true,
+ defaultType: 'textfield',
+ buttonAlign: 'left',
+ items: items,
+ buttons: [undoBtn, saveBtn]
+ });
+
+ /* Create window */
+ win = new Ext.Window({
+ title: 'Map services',
+ layout: 'fit',
+ autoWidth: true,
+ autoHeight: true,
+ plain: true,
+ items: panel
+ });
+
+ win.show();
+};
*/
tvheadend.status_subs = function() {
- tvheadend.subsStore = new Ext.data.JsonStore({
- root : 'entries',
- totalProperty : 'totalCount',
- fields : [ {
- name : 'id'
- }, {
- name : 'hostname'
- }, {
- name : 'username'
- }, {
- name : 'title'
- }, {
- name : 'channel'
- }, {
- name : 'service'
- }, {
- name : 'state'
- }, {
- name : 'errors'
- }, {
- name : 'in'
- }, {
- name : 'out'
- }, {
- name : 'start',
- type : 'date',
- dateFormat : 'U' /* unix time */
- } ],
- url : 'api/status/subscriptions',
- autoLoad : true,
- id : 'id'
- });
-
-
-
- tvheadend.comet.on('subscriptions', function(m) {
-
- if (m.reload != null) tvheadend.subsStore.reload();
-
- if (m.updateEntry != null) {
- r = tvheadend.subsStore.getById(m.id)
- if (typeof r === 'undefined') {
- tvheadend.subsStore.reload();
- return;
- }
-
- r.data.channel = m.channel;
- r.data.service = m.service;
- r.data.state = m.state;
- r.data.errors = m.errors;
- r.data.in = m.in;
- r.data.out = m.out;
-
- tvheadend.subsStore.afterEdit(r);
- tvheadend.subsStore.fireEvent('updated', tvheadend.subsStore, r,
- Ext.data.Record.COMMIT);
- }
- });
-
- function renderDate(value) {
- var dt = new Date(value);
- return dt.format('D j M H:i');
- }
-
- function renderBw(value, item, store) {
- var txt = parseInt(value / 125);
- var href = 'javascript:tvheadend.subscription_bw_monitor(' + store.id + ');';
- return '<a href="' + href + '">' + txt + '</a>';
- }
-
- var subsCm = new Ext.grid.ColumnModel([{
- width : 50,
- id : 'hostname',
- header : "Hostname",
- dataIndex : 'hostname'
- }, {
- width : 50,
- id : 'username',
- header : "Username",
- dataIndex : 'username'
- }, {
- width : 80,
- id : 'title',
- header : "Title",
- dataIndex : 'title'
- }, {
- width : 50,
- id : 'channel',
- header : "Channel",
- dataIndex : 'channel'
- }, {
- width : 200,
- id : 'service',
- header : "Service",
- dataIndex : 'service',
- }, {
- width : 50,
- id : 'start',
- header : "Start",
- dataIndex : 'start',
- renderer : renderDate
- }, {
- width : 50,
- id : 'state',
- header : "State",
- dataIndex : 'state'
- }, {
- width : 50,
- id : 'errors',
- header : "Errors",
- dataIndex : 'errors'
- }, {
- width : 50,
- id : 'in',
- header : "Input (kb/s)",
- dataIndex : 'in',
- renderer: renderBw
- }, {
- width : 50,
- id : 'out',
- header : "Output (kb/s)",
- dataIndex : 'out',
- renderer: renderBw
- } ]);
-
- var subs = new Ext.grid.GridPanel({
- border: false,
- loadMask : true,
- stripeRows : true,
- disableSelection : true,
- title : 'Subscriptions',
- iconCls : 'eye',
- store : tvheadend.subsStore,
- cm : subsCm,
- flex: 1,
- viewConfig : {
- forceFit : true
- }
- });
- return subs;
-}
+ tvheadend.subsStore = new Ext.data.JsonStore({
+ root: 'entries',
+ totalProperty: 'totalCount',
+ fields: [{
+ name: 'id'
+ }, {
+ name: 'hostname'
+ }, {
+ name: 'username'
+ }, {
+ name: 'title'
+ }, {
+ name: 'channel'
+ }, {
+ name: 'service'
+ }, {
+ name: 'state'
+ }, {
+ name: 'errors'
+ }, {
+ name: 'in'
+ }, {
+ name: 'out'
+ }, {
+ name: 'start',
+ type: 'date',
+ dateFormat: 'U' /* unix time */
+ }],
+ url: 'api/status/subscriptions',
+ autoLoad: true,
+ id: 'id'
+ });
+
+
+
+ tvheadend.comet.on('subscriptions', function(m) {
+
+ if (m.reload != null)
+ tvheadend.subsStore.reload();
+
+ if (m.updateEntry != null) {
+ r = tvheadend.subsStore.getById(m.id);
+ if (typeof r === 'undefined') {
+ tvheadend.subsStore.reload();
+ return;
+ }
+
+ r.data.channel = m.channel;
+ r.data.service = m.service;
+ r.data.state = m.state;
+ r.data.errors = m.errors;
+ r.data.in = m.in;
+ r.data.out = m.out;
+
+ tvheadend.subsStore.afterEdit(r);
+ tvheadend.subsStore.fireEvent('updated', tvheadend.subsStore, r,
+ Ext.data.Record.COMMIT);
+ }
+ });
+
+ function renderDate(value) {
+ var dt = new Date(value);
+ return dt.format('D j M H:i');
+ }
+
+ function renderBw(value, item, store) {
+ var txt = parseInt(value / 125);
+ var href = 'javascript:tvheadend.subscription_bw_monitor(' + store.id + ');';
+ return '<a href="' + href + '">' + txt + '</a>';
+ }
+
+ var subsCm = new Ext.grid.ColumnModel([{
+ width: 50,
+ id: 'hostname',
+ header: "Hostname",
+ dataIndex: 'hostname'
+ }, {
+ width: 50,
+ id: 'username',
+ header: "Username",
+ dataIndex: 'username'
+ }, {
+ width: 80,
+ id: 'title',
+ header: "Title",
+ dataIndex: 'title'
+ }, {
+ width: 50,
+ id: 'channel',
+ header: "Channel",
+ dataIndex: 'channel'
+ }, {
+ width: 200,
+ id: 'service',
+ header: "Service",
+ dataIndex: 'service'
+ }, {
+ width: 50,
+ id: 'start',
+ header: "Start",
+ dataIndex: 'start',
+ renderer: renderDate
+ }, {
+ width: 50,
+ id: 'state',
+ header: "State",
+ dataIndex: 'state'
+ }, {
+ width: 50,
+ id: 'errors',
+ header: "Errors",
+ dataIndex: 'errors'
+ }, {
+ width: 50,
+ id: 'in',
+ header: "Input (kb/s)",
+ dataIndex: 'in',
+ renderer: renderBw
+ }, {
+ width: 50,
+ id: 'out',
+ header: "Output (kb/s)",
+ dataIndex: 'out',
+ renderer: renderBw
+ }]);
+
+ var subs = new Ext.grid.GridPanel({
+ border: false,
+ loadMask: true,
+ stripeRows: true,
+ disableSelection: true,
+ title: 'Subscriptions',
+ iconCls: 'eye',
+ store: tvheadend.subsStore,
+ cm: subsCm,
+ flex: 1,
+ viewConfig: {
+ forceFit: true
+ }
+ });
+ return subs;
+};
/**
*/
tvheadend.status_streams = function() {
- tvheadend.streamStatusStore = new Ext.data.JsonStore({
- root : 'entries',
- totalProperty : 'totalCount',
- fields : [ {
- name : 'uuid'
- }, {
- name : 'input'
- }, {
- name : 'username'
- }, {
- name : 'stream'
- }, {
- name : 'subs'
- }, {
- name : 'weight'
- }, {
- name : 'signal'
- }, {
- name : 'ber'
- }, {
- name : 'unc'
- }, {
- name : 'snr'
- }, {
- name : 'bps'
- }, {
- name : 'cc'
- }, {
- name : 'te'
- },
- ],
- url : 'api/status/inputs',
- autoLoad : true,
- id : 'uuid'
- });
-
- tvheadend.comet.on('input_status', function(m){
- if (m.reload != null) tvheadend.streamStatusStore.reload();
- if (m.update != null) {
- var r = tvheadend.streamStatusStore.getById(m.uuid);
- if (r) {
- r.data.subs = m.subs;
- r.data.weight = m.weight;
- r.data.signal = m.signal;
- r.data.ber = m.ber;
- r.data.unc = m.unc;
- r.data.snr = m.snr;
- r.data.bps = m.bps;
- r.data.cc = m.cc;
- r.data.te = m.te;
-
- tvheadend.streamStatusStore.afterEdit(r);
- tvheadend.streamStatusStore.fireEvent('updated',
- tvheadend.streamStatusStore,
- r,
- Ext.data.Record.COMMIT);
- } else {
- tvheadend.streamStatusStore.reload();
- }
+ tvheadend.streamStatusStore = new Ext.data.JsonStore({
+ root: 'entries',
+ totalProperty: 'totalCount',
+ fields: [{
+ name: 'uuid'
+ }, {
+ name: 'input'
+ }, {
+ name: 'username'
+ }, {
+ name: 'stream'
+ }, {
+ name: 'subs'
+ }, {
+ name: 'weight'
+ }, {
+ name: 'signal'
+ }, {
+ name: 'ber'
+ }, {
+ name: 'unc'
+ }, {
+ name: 'snr'
+ }, {
+ name: 'bps'
+ }, {
+ name: 'cc'
+ }, {
+ name: 'te'
+ }
+ ],
+ url: 'api/status/inputs',
+ autoLoad: true,
+ id: 'uuid'
+ });
+
+ tvheadend.comet.on('input_status', function(m) {
+ if (m.reload != null)
+ tvheadend.streamStatusStore.reload();
+ if (m.update != null) {
+ var r = tvheadend.streamStatusStore.getById(m.uuid);
+ if (r) {
+ r.data.subs = m.subs;
+ r.data.weight = m.weight;
+ r.data.signal = m.signal;
+ r.data.ber = m.ber;
+ r.data.unc = m.unc;
+ r.data.snr = m.snr;
+ r.data.bps = m.bps;
+ r.data.cc = m.cc;
+ r.data.te = m.te;
+
+ tvheadend.streamStatusStore.afterEdit(r);
+ tvheadend.streamStatusStore.fireEvent('updated',
+ tvheadend.streamStatusStore,
+ r,
+ Ext.data.Record.COMMIT);
+ } else {
+ tvheadend.streamStatusStore.reload();
+ }
+ }
+ });
+
+ var signal = new Ext.ux.grid.ProgressColumn({
+ header: "Signal Strength",
+ dataIndex: 'signal',
+ width: 85,
+ textPst: '%',
+ colored: true
+ });
+
+ function renderBw(value, item, store) {
+ var txt = parseInt(value / 1024);
+ var href = "javascript:tvheadend.stream_bw_monitor('" + store.id + "');";
+ return '<a href="' + href + '">' + txt + '</a>';
}
- });
-
- var signal = new Ext.ux.grid.ProgressColumn({
- header : "Signal Strength",
- dataIndex : 'signal',
- width : 85,
- textPst : '%',
- colored : true
- });
-
- function renderBw(value, item, store) {
- var txt = parseInt(value / 1024);
- var href = "javascript:tvheadend.stream_bw_monitor('" + store.id + "');";
- return '<a href="' + href + '">' + txt + '</a>';
- }
-
- var cm = new Ext.grid.ColumnModel([{
- width : 100,
- header : "Input",
- dataIndex : 'input'
- },{
- width : 100,
- header : "Stream",
- dataIndex : 'stream'
- },{
- width : 50,
- header : "Subs #",
- dataIndex : 'subs'
- },{
- width : 50,
- header : "Weight",
- dataIndex : 'weight'
- },{
- width : 50,
- header : "Bandwidth (kb/s)",
- dataIndex : 'bps',
- renderer: renderBw
- },{
- width : 50,
- header : "BER",
- dataIndex : 'ber'
- },{
- width : 50,
- header : "Uncorrected BER",
- dataIndex : 'unc'
- },{
- width : 50,
- header : "Transport Error",
- dataIndex : 'te'
- },{
- width : 50,
- header : "Continuity Error",
- dataIndex : 'cc'
- },{
- width : 50,
- header : "SNR",
- dataIndex : 'snr',
- renderer: function(value) {
- if(value > 0) {
- return value.toFixed(1) + " dB";
- } else {
- return '<span class="tvh-grid-unset">Unknown</span>';
- }
+
+ var cm = new Ext.grid.ColumnModel([{
+ width: 100,
+ header: "Input",
+ dataIndex: 'input'
+ }, {
+ width: 100,
+ header: "Stream",
+ dataIndex: 'stream'
+ }, {
+ width: 50,
+ header: "Subs #",
+ dataIndex: 'subs'
+ }, {
+ width: 50,
+ header: "Weight",
+ dataIndex: 'weight'
+ }, {
+ width: 50,
+ header: "Bandwidth (kb/s)",
+ dataIndex: 'bps',
+ renderer: renderBw
+ }, {
+ width: 50,
+ header: "BER",
+ dataIndex: 'ber'
+ }, {
+ width: 50,
+ header: "Uncorrected BER",
+ dataIndex: 'unc'
+ }, {
+ width: 50,
+ header: "Transport Error",
+ dataIndex: 'te'
+ }, {
+ width: 50,
+ header: "Continuity Error",
+ dataIndex: 'cc'
+ }, {
+ width: 50,
+ header: "SNR",
+ dataIndex: 'snr',
+ renderer: function(value) {
+ if (value > 0) {
+ return value.toFixed(1) + " dB";
+ } else {
+ return '<span class="tvh-grid-unset">Unknown</span>';
}
+ }
}, signal]);
- var panel = new Ext.grid.GridPanel({
- border: false,
- loadMask : true,
- stripeRows : true,
- disableSelection : true,
- title : 'Stream',
- iconCls : 'hardware',
- store : tvheadend.streamStatusStore,
- cm : cm,
- flex: 1,
- viewConfig : {
- forceFit : true
- }
- });
- return panel;
-}
+ var panel = new Ext.grid.GridPanel({
+ border: false,
+ loadMask: true,
+ stripeRows: true,
+ disableSelection: true,
+ title: 'Stream',
+ iconCls: 'hardware',
+ store: tvheadend.streamStatusStore,
+ cm: cm,
+ flex: 1,
+ viewConfig: {
+ forceFit: true
+ }
+ });
+ return panel;
+};
/**
*
*/
tvheadend.status_conns = function() {
- var store = new Ext.data.JsonStore({
- root : 'entries',
- totalProperty : 'totalCount',
- fields : [ {
- name : 'id'
- }, {
- name : 'type'
- }, {
- name : 'peer'
- }, {
- name : 'user'
- }, {
- name : 'started',
- type : 'date',
- dateFormat : 'U' /* unix time */
- } ],
- url : 'api/status/connections',
- autoLoad : true,
- id : 'id'
- });
-
- tvheadend.comet.on('connections', function(m) {
- if (m.reload != null) store.reload();
- });
-
- function renderDate(value) {
- var dt = new Date(value);
- return dt.format('Y-m-d H:i:s');
- }
-
- var cm = new Ext.grid.ColumnModel([{
- width : 50,
- id : 'type',
- header : "Type",
- dataIndex : 'type'
- }, {
- width : 50,
- id : 'peer',
- header : "IP Address",
- dataIndex : 'peer'
- }, {
- width : 50,
- id : 'user',
- header : "Username",
- dataIndex : 'user'
- }, {
- width : 50,
- id : 'started',
- header : "Started",
- dataIndex : 'started',
- renderer : renderDate
- } ]);
-
- var panel = new Ext.grid.GridPanel({
- border: false,
- loadMask : true,
- stripeRows : true,
- disableSelection : true,
- title : 'Connections',
- iconCls : 'eye',
- store : store,
- cm : cm,
- flex: 1,
- viewConfig : {
- forceFit : true
- }
- });
- return panel;
-}
+ var store = new Ext.data.JsonStore({
+ root: 'entries',
+ totalProperty: 'totalCount',
+ fields: [{
+ name: 'id'
+ }, {
+ name: 'type'
+ }, {
+ name: 'peer'
+ }, {
+ name: 'user'
+ }, {
+ name: 'started',
+ type: 'date',
+ dateFormat: 'U' /* unix time */
+ }],
+ url: 'api/status/connections',
+ autoLoad: true,
+ id: 'id'
+ });
+
+ tvheadend.comet.on('connections', function(m) {
+ if (m.reload != null)
+ store.reload();
+ });
+
+ function renderDate(value) {
+ var dt = new Date(value);
+ return dt.format('Y-m-d H:i:s');
+ }
+
+ var cm = new Ext.grid.ColumnModel([{
+ width: 50,
+ id: 'type',
+ header: "Type",
+ dataIndex: 'type'
+ }, {
+ width: 50,
+ id: 'peer',
+ header: "IP Address",
+ dataIndex: 'peer'
+ }, {
+ width: 50,
+ id: 'user',
+ header: "Username",
+ dataIndex: 'user'
+ }, {
+ width: 50,
+ id: 'started',
+ header: "Started",
+ dataIndex: 'started',
+ renderer: renderDate
+ }]);
+
+ var panel = new Ext.grid.GridPanel({
+ border: false,
+ loadMask: true,
+ stripeRows: true,
+ disableSelection: true,
+ title: 'Connections',
+ iconCls: 'eye',
+ store: store,
+ cm: cm,
+ flex: 1,
+ viewConfig: {
+ forceFit: true
+ }
+ });
+ return panel;
+};
tvheadend.status = function() {
- var panel = new Ext.TabPanel({
- title : 'Status',
- autoScroll : true,
- activeTab : 0,
- iconCls : 'eye',
- items : [
- new tvheadend.status_streams,
- new tvheadend.status_subs,
- new tvheadend.status_conns,
- new tvheadend.service_mapper_status
- ]
- });
- return panel;
-}
+ var panel = new Ext.TabPanel({
+ title: 'Status',
+ autoScroll: true,
+ activeTab: 0,
+ iconCls: 'eye',
+ items: [
+ new tvheadend.status_streams,
+ new tvheadend.status_subs,
+ new tvheadend.status_conns,
+ new tvheadend.service_mapper_status
+ ]
+ });
+ return panel;
+};
tvheadend.subscription_bw_monitor = function(id) {
- var inputSeries = new TimeSeries();
+ var inputSeries = new TimeSeries();
var outputSeries = new TimeSeries();
var chart = new SmoothieChart({
- minValue: 0,
- grid: {
- sharpLines: true,
- fillStyle: 'transparent',
- verticalSections: 0,
- millisPerLine: 0
- },
- labels: {
- disabled: false,
- fillStyle: '#000000',
- fontSize: 12
- }
+ minValue: 0,
+ grid: {
+ sharpLines: true,
+ fillStyle: 'transparent',
+ verticalSections: 0,
+ millisPerLine: 0
+ },
+ labels: {
+ disabled: false,
+ fillStyle: '#000000',
+ fontSize: 12
+ }
});
chart.addTimeSeries(inputSeries, {
- strokeStyle: 'rgb(0, 255, 0)',
- fillStyle: 'rgba(0, 255, 0, 0.5)',
- lineWidth: 3
+ strokeStyle: 'rgb(0, 255, 0)',
+ fillStyle: 'rgba(0, 255, 0, 0.5)',
+ lineWidth: 3
});
chart.addTimeSeries(outputSeries, {
- strokeStyle: 'rgb(255, 0, 255)',
- fillStyle: 'rgba(255, 0, 255, 0.5)',
- lineWidth: 3
+ strokeStyle: 'rgb(255, 0, 255)',
+ fillStyle: 'rgba(255, 0, 255, 0.5)',
+ lineWidth: 3
});
-
+
var inputLbl = new Ext.form.Label();
var outputLbl = new Ext.form.Label();
var comprLbl = new Ext.form.Label();
var win = new Ext.Window({
title: 'Bandwidth monitor',
- layout:'fit',
- resizable: false,
- width : 450 + 30,
- height : 150 + 50,
- constrainHeader : true,
- tbar : [inputLbl, '-', outputLbl, '-', comprLbl],
- items: {
- xtype: 'box',
- autoEl: {
- tag: 'canvas',
- width: 450,
- height: 150
- },
- listeners: {
- render: {
- scope: this,
- fn: function(item) {
- chart.streamTo(item.el.dom, 1000);
- }
- },
+ layout: 'fit',
+ resizable: false,
+ width: 450 + 30,
+ height: 150 + 50,
+ constrainHeader: true,
+ tbar: [inputLbl, '-', outputLbl, '-', comprLbl],
+ items: {
+ xtype: 'box',
+ autoEl: {
+ tag: 'canvas',
+ width: 450,
+ height: 150
+ },
+ listeners: {
+ render: {
+ scope: this,
+ fn: function(item) {
+ chart.streamTo(item.el.dom, 1000);
+ }
+ },
resize: {
- scope: this,
- fn: function(item) {
- chart.render(item.el.dom, 1000);
+ scope: this,
+ fn: function(item) {
+ chart.render(item.el.dom, 1000);
}
- }
- }
- }
+ }
+ }
+ }
});
var task = {
- interval: 1000,
- run: function() {
- r = tvheadend.subsStore.getById(id);
- if (typeof r === 'undefined') {
- chart.stop();
- Ext.TaskMgr.stop(task);
- return;
- }
-
- var input = Math.round(r.data.in / 125);
- var output = Math.round(r.data.out / 125);
- var ratio = new Number(r.data.in / r.data.out).toPrecision(3);
-
- win.setTitle(r.data.channel);
- inputLbl.setText('In: ' + input + ' kb/s');
- outputLbl.setText('Out: ' + output + ' kb/s');
- comprLbl.setText('Compression ratio: ' + ratio);
-
- inputSeries.append(new Date().getTime(), input);
- outputSeries.append(new Date().getTime(), output);
- }
+ interval: 1000,
+ run: function() {
+ r = tvheadend.subsStore.getById(id);
+ if (typeof r === 'undefined') {
+ chart.stop();
+ Ext.TaskMgr.stop(task);
+ return;
+ }
+
+ var input = Math.round(r.data.in / 125);
+ var output = Math.round(r.data.out / 125);
+ var ratio = new Number(r.data.in / r.data.out).toPrecision(3);
+
+ win.setTitle(r.data.channel);
+ inputLbl.setText('In: ' + input + ' kb/s');
+ outputLbl.setText('Out: ' + output + ' kb/s');
+ comprLbl.setText('Compression ratio: ' + ratio);
+
+ inputSeries.append(new Date().getTime(), input);
+ outputSeries.append(new Date().getTime(), output);
+ }
};
win.on('close', function() {
- chart.stop();
- Ext.TaskMgr.stop(task);
+ chart.stop();
+ Ext.TaskMgr.stop(task);
});
win.show();
-
+
Ext.TaskMgr.start(task);
};
tvheadend.stream_bw_monitor = function(id) {
- var inputSeries = new TimeSeries();
+ var inputSeries = new TimeSeries();
var chart = new SmoothieChart({
- minValue: 0,
- grid: {
- sharpLines: true,
- fillStyle: 'transparent',
- verticalSections: 0,
- millisPerLine: 0
- },
- labels: {
- disabled: false,
- fillStyle: '#000000',
- fontSize: 12
- }
+ minValue: 0,
+ grid: {
+ sharpLines: true,
+ fillStyle: 'transparent',
+ verticalSections: 0,
+ millisPerLine: 0
+ },
+ labels: {
+ disabled: false,
+ fillStyle: '#000000',
+ fontSize: 12
+ }
});
chart.addTimeSeries(inputSeries, {
- strokeStyle: 'rgb(0, 255, 0)',
- fillStyle: 'rgba(0, 255, 0, 0.5)',
- lineWidth: 3
+ strokeStyle: 'rgb(0, 255, 0)',
+ fillStyle: 'rgba(0, 255, 0, 0.5)',
+ lineWidth: 3
});
var inputLbl = new Ext.form.Label();
var win = new Ext.Window({
title: 'Bandwidth monitor',
- layout:'fit',
- resizable: false,
- width : 450 + 30,
- height : 150 + 50,
- constrainHeader : true,
- tbar : [inputLbl],
- items: {
- xtype: 'box',
- autoEl: {
- tag: 'canvas',
- width: 450,
- height: 150
- },
- listeners: {
- render: {
- scope: this,
- fn: function(item) {
- chart.streamTo(item.el.dom, 1000);
- }
- },
+ layout: 'fit',
+ resizable: false,
+ width: 450 + 30,
+ height: 150 + 50,
+ constrainHeader: true,
+ tbar: [inputLbl],
+ items: {
+ xtype: 'box',
+ autoEl: {
+ tag: 'canvas',
+ width: 450,
+ height: 150
+ },
+ listeners: {
+ render: {
+ scope: this,
+ fn: function(item) {
+ chart.streamTo(item.el.dom, 1000);
+ }
+ },
resize: {
- scope: this,
- fn: function(item) {
- chart.render(item.el.dom, 1000);
+ scope: this,
+ fn: function(item) {
+ chart.render(item.el.dom, 1000);
}
- }
- }
- }
+ }
+ }
+ }
});
var task = {
- interval: 1000,
- run: function() {
- r = tvheadend.streamStatusStore.getById(id);
- if (typeof r === 'undefined') {
- chart.stop();
- Ext.TaskMgr.stop(task);
- return;
- }
-
- win.setTitle(r.data.input + ' (' + r.data.stream + ')');
- var input = Math.round(r.data.bps / 1024);
- inputLbl.setText('Input: ' + input + ' kb/s');
- inputSeries.append(new Date().getTime(), input);
- }
+ interval: 1000,
+ run: function() {
+ r = tvheadend.streamStatusStore.getById(id);
+ if (typeof r === 'undefined') {
+ chart.stop();
+ Ext.TaskMgr.stop(task);
+ return;
+ }
+
+ win.setTitle(r.data.input + ' (' + r.data.stream + ')');
+ var input = Math.round(r.data.bps / 1024);
+ inputLbl.setText('Input: ' + input + ' kb/s');
+ inputSeries.append(new Date().getTime(), input);
+ }
};
win.on('close', function() {
- chart.stop();
- Ext.TaskMgr.stop(task);
+ chart.stop();
+ Ext.TaskMgr.stop(task);
});
win.show();
tvheadend.tableEditor = function(title, dtable, cm, rec, plugins, store,
- helpContent, icon) {
+ helpContent, icon) {
- if (store == null) {
- store = new Ext.data.JsonStore({
- root : 'entries',
- fields : rec,
- url : "tablemgr",
- autoLoad : true,
- id : 'id',
- baseParams : {
- table : dtable,
- op : "get"
- }
- });
- }
+ if (store == null) {
+ store = new Ext.data.JsonStore({
+ root: 'entries',
+ fields: rec,
+ url: "tablemgr",
+ autoLoad: true,
+ id: 'id',
+ baseParams: {
+ table: dtable,
+ op: "get"
+ }
+ });
+ }
- tvheadend.comet.on(dtable, function(m){
- if (m.reload)
- store.reload();
- });
+ tvheadend.comet.on(dtable, function(m) {
+ if (m.reload)
+ store.reload();
+ });
- function addRecord() {
- Ext.Ajax.request({
- url : "tablemgr",
- params : {
- op : "create",
- table : dtable
- },
- failure : function(response, options) {
- Ext.MessageBox.alert('Server Error',
- 'Unable to generate new record');
- },
- success : function(response, options) {
- var responseData = Ext.util.JSON.decode(response.responseText);
- var p = new rec(responseData, responseData.id);
- grid.stopEditing();
- store.insert(0, p);
- grid.startEditing(0, 0);
- }
- })
- }
- ;
+ function addRecord() {
+ Ext.Ajax.request({
+ url: "tablemgr",
+ params: {
+ op: "create",
+ table: dtable
+ },
+ failure: function(response, options) {
+ Ext.MessageBox.alert('Server Error',
+ 'Unable to generate new record');
+ },
+ success: function(response, options) {
+ var responseData = Ext.util.JSON.decode(response.responseText);
+ var p = new rec(responseData, responseData.id);
+ grid.stopEditing();
+ store.insert(0, p);
+ grid.startEditing(0, 0);
+ }
+ });
+ }
+ ;
- function delSelected() {
- var selectedKeys = grid.selModel.selections.keys;
- if (selectedKeys.length > 0) {
- Ext.MessageBox.confirm('Message',
- 'Do you really want to delete selection?', deleteRecord);
- }
- else {
- Ext.MessageBox.alert('Message',
- 'Please select at least one item to delete');
- }
- }
- ;
+ function delSelected() {
+ var selectedKeys = grid.selModel.selections.keys;
+ if (selectedKeys.length > 0) {
+ Ext.MessageBox.confirm('Message',
+ 'Do you really want to delete selection?', deleteRecord);
+ }
+ else {
+ Ext.MessageBox.alert('Message',
+ 'Please select at least one item to delete');
+ }
+ }
+ ;
- function deleteRecord(btn) {
- if (btn == 'yes') {
- var selectedKeys = grid.selModel.selections.keys;
+ function deleteRecord(btn) {
+ if (btn === 'yes') {
+ var selectedKeys = grid.selModel.selections.keys;
- Ext.Ajax.request({
- url : "tablemgr",
- params : {
- op : "delete",
- table : dtable,
- entries : Ext.encode(selectedKeys)
- },
- failure : function(response, options) {
- Ext.MessageBox.alert('Server Error', 'Unable to delete');
- },
- success : function(response, options) {
- }
- })
- }
- }
+ Ext.Ajax.request({
+ url: "tablemgr",
+ params: {
+ op: "delete",
+ table: dtable,
+ entries: Ext.encode(selectedKeys)
+ },
+ failure: function(response, options) {
+ Ext.MessageBox.alert('Server Error', 'Unable to delete');
+ },
+ success: function(response, options) {
+ }
+ });
+ }
+ }
- function saveChanges() {
- var mr = store.getModifiedRecords();
- var out = new Array();
- for ( var x = 0; x < mr.length; x++) {
- v = mr[x].getChanges();
- out[x] = v;
- out[x].id = mr[x].id;
- }
+ function saveChanges() {
+ var mr = store.getModifiedRecords();
+ var out = new Array();
+ for (var x = 0; x < mr.length; x++) {
+ v = mr[x].getChanges();
+ out[x] = v;
+ out[x].id = mr[x].id;
+ }
- Ext.Ajax.request({
- url : "tablemgr",
- params : {
- op : "update",
- table : dtable,
- entries : Ext.encode(out)
- },
- success : function(response, options) {
- // Note: this call is mostly redundant (comet update will pick it up anyway)
- store.commitChanges();
- },
- failure : function(response, options) {
- Ext.MessageBox.alert('Message', response.statusText);
- }
- });
- }
+ Ext.Ajax.request({
+ url: "tablemgr",
+ params: {
+ op: "update",
+ table: dtable,
+ entries: Ext.encode(out)
+ },
+ success: function(response, options) {
+ // Note: this call is mostly redundant (comet update will pick it up anyway)
+ store.commitChanges();
+ },
+ failure: function(response, options) {
+ Ext.MessageBox.alert('Message', response.statusText);
+ }
+ });
+ }
- var selModel = new Ext.grid.RowSelectionModel({
- singleSelect : false
- });
+ var selModel = new Ext.grid.RowSelectionModel({
+ singleSelect: false
+ });
- var delButton = new Ext.Toolbar.Button({
- tooltip : 'Delete one or more selected rows',
- iconCls : 'remove',
- text : 'Delete selected',
- handler : delSelected,
- disabled : true
- });
+ var delButton = new Ext.Toolbar.Button({
+ tooltip: 'Delete one or more selected rows',
+ iconCls: 'remove',
+ text: 'Delete selected',
+ handler: delSelected,
+ disabled: true
+ });
- var saveBtn = new Ext.Toolbar.Button({
- tooltip : 'Save any changes made (Changed cells have red borders)',
- iconCls : 'save',
- text : "Save changes",
- handler : saveChanges,
- disabled : true
- });
+ var saveBtn = new Ext.Toolbar.Button({
+ tooltip: 'Save any changes made (Changed cells have red borders)',
+ iconCls: 'save',
+ text: "Save changes",
+ handler: saveChanges,
+ disabled: true
+ });
- var rejectBtn = new Ext.Toolbar.Button({
- tooltip : 'Revert any changes made (Changed cells have red borders)',
- iconCls : 'undo',
- text : "Revert changes",
- handler : function() {
- store.rejectChanges();
- },
- disabled : true
- });
+ var rejectBtn = new Ext.Toolbar.Button({
+ tooltip: 'Revert any changes made (Changed cells have red borders)',
+ iconCls: 'undo',
+ text: "Revert changes",
+ handler: function() {
+ store.rejectChanges();
+ },
+ disabled: true
+ });
- store.on('update', function(s, r, o) {
- d = s.getModifiedRecords().length == 0
- saveBtn.setDisabled(d);
- rejectBtn.setDisabled(d);
- });
+ store.on('update', function(s, r, o) {
+ d = s.getModifiedRecords().length === 0;
+ saveBtn.setDisabled(d);
+ rejectBtn.setDisabled(d);
+ });
- selModel.on('selectionchange', function(self) {
- if (self.getCount() > 0) {
- delButton.enable();
- }
- else {
- delButton.disable();
- }
- });
+ selModel.on('selectionchange', function(self) {
+ if (self.getCount() > 0) {
+ delButton.enable();
+ }
+ else {
+ delButton.disable();
+ }
+ });
- var grid = new Ext.grid.EditorGridPanel({
- title : title,
- iconCls : icon,
- plugins : plugins,
- store : store,
- clicksToEdit : 2,
- cm : cm,
- viewConfig : {
- forceFit : true
- },
- selModel : selModel,
- stripeRows : true,
- tbar : [
- {
- tooltip : 'Create a new entry on the server. '
- + 'The new entry is initially disabled so it must be enabled '
- + 'before it start taking effect.',
- iconCls : 'add',
- text : 'Add entry',
- handler : addRecord
- }, '-', delButton, '-', saveBtn, rejectBtn, '->', {
- text : 'Help',
- handler : function() {
- new tvheadend.help(title, helpContent);
- }
- } ]
- });
- return grid;
-}
+ var grid = new Ext.grid.EditorGridPanel({
+ title: title,
+ iconCls: icon,
+ plugins: plugins,
+ store: store,
+ clicksToEdit: 2,
+ cm: cm,
+ viewConfig: {
+ forceFit: true
+ },
+ selModel: selModel,
+ stripeRows: true,
+ tbar: [
+ {
+ tooltip: 'Create a new entry on the server. '
+ + 'The new entry is initially disabled so it must be enabled '
+ + 'before it start taking effect.',
+ iconCls: 'add',
+ text: 'Add entry',
+ handler: addRecord
+ }, '-', delButton, '-', saveBtn, rejectBtn, '->', {
+ text: 'Help',
+ handler: function() {
+ new tvheadend.help(title, helpContent);
+ }
+ }]
+ });
+ return grid;
+};
tvheadend.timeshift = function() {
- /* ****************************************************************
- * Data
- * ***************************************************************/
-
- var confreader = new Ext.data.JsonReader(
- {
- root: 'config'
- },
+ /* ****************************************************************
+ * Data
+ * ***************************************************************/
+
+ var confreader = new Ext.data.JsonReader(
+ {
+ root: 'config'
+ },
[
- 'timeshift_enabled', 'timeshift_ondemand',
- 'timeshift_path',
- 'timeshift_unlimited_period', 'timeshift_max_period',
- 'timeshift_unlimited_size', 'timeshift_max_size'
+ 'timeshift_enabled', 'timeshift_ondemand',
+ 'timeshift_path',
+ 'timeshift_unlimited_period', 'timeshift_max_period',
+ 'timeshift_unlimited_size', 'timeshift_max_size'
]
- );
-
- /* ****************************************************************
- * Fields
- * ***************************************************************/
-
- var timeshiftEnabled = new Ext.form.Checkbox({
- fieldLabel: 'Enabled',
- name: 'timeshift_enabled',
- width: 300
- });
-
- var timeshiftOndemand = new Ext.form.Checkbox({
- fieldLabel: 'On-Demand',
- name: 'timeshift_ondemand',
- width: 300
- });
-
- var timeshiftPath = new Ext.form.TextField({
- fieldLabel: 'Storage Path',
- name: 'timeshift_path',
- allowBlank: true,
- width: 300
- });
-
- var timeshiftMaxPeriod = new Ext.form.NumberField({
- fieldLabel: 'Max. Period (mins)',
- name: 'timeshift_max_period',
- allowBlank: false,
- width: 300
- });
-
- var timeshiftUnlPeriod = new Ext.form.Checkbox({
- fieldLabel: ' (unlimited)',
- name: 'timeshift_unlimited_period',
- Width: 300
- });
-
- var timeshiftMaxSize = new Ext.form.NumberField({
- fieldLabel: 'Max. Size (MB)',
- name: 'timeshift_max_size',
- allowBlank: false,
- width: 300
- });
-
- var timeshiftUnlSize = new Ext.form.Checkbox({
- fieldLabel: ' (unlimited)',
- name: 'timeshift_unlimited_size',
- Width: 300
- });
-
- /* ****************************************************************
- * Events
- * ***************************************************************/
-
- timeshiftUnlPeriod.on('check', function(e, c){
- timeshiftMaxPeriod.setDisabled(c);
- });
- timeshiftUnlSize.on('check', function(e, c){
- timeshiftMaxSize.setDisabled(c);
- });
-
- /* ****************************************************************
- * Form
- * ***************************************************************/
-
- var saveButton = new Ext.Button({
- text : "Save configuration",
- tooltip : 'Save changes made to configuration below',
- iconCls : 'save',
- handler : saveChanges
- });
-
- var helpButton = new Ext.Button({
- text : 'Help',
- handler : function() {
- new tvheadend.help('Timeshift Configuration', 'config_timeshift.html');
- }
- });
-
- var confpanel = new Ext.FormPanel({
- title : 'Timeshift',
- iconCls : 'clock',
- border : false,
- bodyStyle : 'padding:15px',
- labelAlign : 'left',
- labelWidth : 150,
- waitMsgTarget : true,
- reader : confreader,
- layout : 'form',
- defaultType : 'textfield',
- autoHeight : true,
- items : [
- timeshiftEnabled, timeshiftOndemand,
- timeshiftPath,
- timeshiftMaxPeriod, timeshiftUnlPeriod,
- timeshiftMaxSize, timeshiftUnlSize
- ],
- tbar : [ saveButton, '->', helpButton ]
- });
-
- /* ****************************************************************
- * Load/Save
- * ***************************************************************/
-
- confpanel.on('render', function() {
- confpanel.getForm().load({
- url: 'timeshift',
- params: {
- 'op': 'loadSettings'
- },
- success: function() {
- confpanel.enable();
- timeshiftMaxPeriod.setDisabled(timeshiftUnlPeriod.getValue());
- timeshiftMaxSize.setDisabled(timeshiftUnlSize.getValue());
- }
+ );
+
+ /* ****************************************************************
+ * Fields
+ * ***************************************************************/
+
+ var timeshiftEnabled = new Ext.form.Checkbox({
+ fieldLabel: 'Enabled',
+ name: 'timeshift_enabled',
+ width: 300
+ });
+
+ var timeshiftOndemand = new Ext.form.Checkbox({
+ fieldLabel: 'On-Demand',
+ name: 'timeshift_ondemand',
+ width: 300
+ });
+
+ var timeshiftPath = new Ext.form.TextField({
+ fieldLabel: 'Storage Path',
+ name: 'timeshift_path',
+ allowBlank: true,
+ width: 300
});
- });
-
- function saveChanges() {
- confpanel.getForm().submit({
- url : 'timeshift',
- params : {
- op : 'saveSettings',
- },
- waitMsg : 'Saving Data...',
- success : function(form, action) {
- },
- failure : function(form, action) {
- Ext.Msg.alert('Save failed', action.result.errormsg);
- }
+
+ var timeshiftMaxPeriod = new Ext.form.NumberField({
+ fieldLabel: 'Max. Period (mins)',
+ name: 'timeshift_max_period',
+ allowBlank: false,
+ width: 300
});
- }
- return confpanel;
-}
+ var timeshiftUnlPeriod = new Ext.form.Checkbox({
+ fieldLabel: ' (unlimited)',
+ name: 'timeshift_unlimited_period',
+ Width: 300
+ });
+
+ var timeshiftMaxSize = new Ext.form.NumberField({
+ fieldLabel: 'Max. Size (MB)',
+ name: 'timeshift_max_size',
+ allowBlank: false,
+ width: 300
+ });
+
+ var timeshiftUnlSize = new Ext.form.Checkbox({
+ fieldLabel: ' (unlimited)',
+ name: 'timeshift_unlimited_size',
+ Width: 300
+ });
+
+ /* ****************************************************************
+ * Events
+ * ***************************************************************/
+
+ timeshiftUnlPeriod.on('check', function(e, c) {
+ timeshiftMaxPeriod.setDisabled(c);
+ });
+ timeshiftUnlSize.on('check', function(e, c) {
+ timeshiftMaxSize.setDisabled(c);
+ });
+
+ /* ****************************************************************
+ * Form
+ * ***************************************************************/
+
+ var saveButton = new Ext.Button({
+ text: "Save configuration",
+ tooltip: 'Save changes made to configuration below',
+ iconCls: 'save',
+ handler: saveChanges
+ });
+
+ var helpButton = new Ext.Button({
+ text: 'Help',
+ handler: function() {
+ new tvheadend.help('Timeshift Configuration', 'config_timeshift.html');
+ }
+ });
+
+ var confpanel = new Ext.FormPanel({
+ title: 'Timeshift',
+ iconCls: 'clock',
+ border: false,
+ bodyStyle: 'padding:15px',
+ labelAlign: 'left',
+ labelWidth: 150,
+ waitMsgTarget: true,
+ reader: confreader,
+ layout: 'form',
+ defaultType: 'textfield',
+ autoHeight: true,
+ items: [
+ timeshiftEnabled, timeshiftOndemand,
+ timeshiftPath,
+ timeshiftMaxPeriod, timeshiftUnlPeriod,
+ timeshiftMaxSize, timeshiftUnlSize
+ ],
+ tbar: [saveButton, '->', helpButton]
+ });
+
+ /* ****************************************************************
+ * Load/Save
+ * ***************************************************************/
+
+ confpanel.on('render', function() {
+ confpanel.getForm().load({
+ url: 'timeshift',
+ params: {
+ 'op': 'loadSettings'
+ },
+ success: function() {
+ confpanel.enable();
+ timeshiftMaxPeriod.setDisabled(timeshiftUnlPeriod.getValue());
+ timeshiftMaxSize.setDisabled(timeshiftUnlSize.getValue());
+ }
+ });
+ });
+
+ function saveChanges() {
+ confpanel.getForm().submit({
+ url: 'timeshift',
+ params: {
+ op: 'saveSettings'
+ },
+ waitMsg: 'Saving Data...',
+ success: function(form, action) {
+ },
+ failure: function(form, action) {
+ Ext.Msg.alert('Save failed', action.result.errormsg);
+ }
+ });
+ }
+
+ return confpanel;
+};
tvheadend.tvadapters = function() {
- return tvheadend.idnode_tree( {
- url : 'api/hardware/tree',
- title : 'TV adapters',
- comet : 'hardware',
- help : function() {
- new tvheadend.help('TV adapters', 'config_tvadapters.html');
- }
- });
-}
+ return tvheadend.idnode_tree({
+ url: 'api/hardware/tree',
+ title: 'TV adapters',
+ comet: 'hardware',
+ help: function() {
+ new tvheadend.help('TV adapters', 'config_tvadapters.html');
+ }
+ });
+};
tvheadend.accessupdate = null;
-tvheadend.capabilties = null;
-tvheadend.conf_chepg = null;
-tvheadend.conf_dvbin = null;
-tvheadend.conf_tsdvr = null;
-tvheadend.conf_csa = null;
+tvheadend.capabilties = null;
+tvheadend.conf_chepg = null;
+tvheadend.conf_dvbin = null;
+tvheadend.conf_tsdvr = null;
+tvheadend.conf_csa = null;
/* State Provider */
Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
- // 7 days from now
- expires : new Date(new Date().getTime()+(1000*60*60*24*7)),
+ // 7 days from now
+ expires: new Date(new Date().getTime() + (1000 * 60 * 60 * 24 * 7))
}));
/**
* Displays a help popup window
*/
tvheadend.help = function(title, pagename) {
- Ext.Ajax.request({
- url : 'docs/' + pagename,
- success : function(result, request) {
-
- var content = new Ext.Panel({
- autoScroll : true,
- border : false,
- layout : 'fit',
- html : result.responseText
- });
-
- var win = new Ext.Window({
- title : 'Help for ' + title,
- layout : 'fit',
- width : 900,
- height : 400,
- constrainHeader : true,
- items : [ content ]
- });
- win.show();
-
- }
- });
-}
+ Ext.Ajax.request({
+ url: 'docs/' + pagename,
+ success: function(result, request) {
+
+ var content = new Ext.Panel({
+ autoScroll: true,
+ border: false,
+ layout: 'fit',
+ html: result.responseText
+ });
+
+ var win = new Ext.Window({
+ title: 'Help for ' + title,
+ layout: 'fit',
+ width: 900,
+ height: 400,
+ constrainHeader: true,
+ items: [content]
+ });
+ win.show();
+
+ }
+ });
+};
/*
* General capabilities
*/
Ext.Ajax.request({
- url: 'capabilities',
- success: function(d)
- {
- if (d && d.responseText)
- tvheadend.capabilities = Ext.util.JSON.decode(d.responseText);
- if (tvheadend.capabilities && tvheadend.accessupdate)
- accessUpdate(tvheadend.accessUpdate);
-
- }
+ url: 'capabilities',
+ success: function(d)
+ {
+ if (d && d.responseText)
+ tvheadend.capabilities = Ext.util.JSON.decode(d.responseText);
+ if (tvheadend.capabilities && tvheadend.accessupdate)
+ accessUpdate(tvheadend.accessUpdate);
+
+ }
});
/**
* Displays a mediaplayer using the html5 video element
*/
tvheadend.VideoPlayer = function(url) {
-
+
var videoPlayer = new tv.ui.VideoPlayer({
- params: {
- resolution: 384
- }
+ params: {
+ resolution: 384
+ }
});
var selectChannel = new Ext.form.ComboBox({
- loadingText : 'Loading...',
- width : 200,
- displayField : 'val',
- store : tvheadend.channels,
- mode : 'local',
- editable : true,
- triggerAction : 'all',
- emptyText : 'Select channel...'
+ loadingText: 'Loading...',
+ width: 200,
+ displayField: 'val',
+ store: tvheadend.channels,
+ mode: 'local',
+ editable: true,
+ triggerAction: 'all',
+ emptyText: 'Select channel...'
});
-
+
selectChannel.on('select', function(c, r) {
- videoPlayer.zapTo(r.id);
+ videoPlayer.zapTo(r.id);
});
var slider = new Ext.Slider({
- width : 135,
- height : 20,
- value : 90,
- increment : 1,
- minValue : 0,
- maxValue : 100
+ width: 135,
+ height: 20,
+ value: 90,
+ increment: 1,
+ minValue: 0,
+ maxValue: 100
});
var sliderLabel = new Ext.form.Label();
sliderLabel.setText("90%");
slider.addListener('change', function() {
- videoPlayer.setVolume(slider.getValue());
- sliderLabel.setText(videoPlayer.getVolume() + '%');
+ videoPlayer.setVolume(slider.getValue());
+ sliderLabel.setText(videoPlayer.getVolume() + '%');
});
var selectResolution = new Ext.form.ComboBox({
width: 150,
- displayField:'name',
+ displayField: 'name',
valueField: 'res',
value: 384,
mode: 'local',
triggerAction: 'all',
emptyText: 'Select resolution...',
store: new Ext.data.SimpleStore({
- fields: ['res','name'],
+ fields: ['res', 'name'],
id: 0,
data: [
- ['288','288p'],
- ['384','384p'],
- ['480','480p'],
- ['576','576p']
+ ['288', '288p'],
+ ['384', '384p'],
+ ['480', '480p'],
+ ['576', '576p']
]
})
});
selectResolution.on('select', function(c, r) {
- videoPlayer.setResolution(r.data.res);
- if(videoPlayer.isIdle())
- return;
-
- var index = selectChannel.selectedIndex;
- if(index < 0)
- return;
-
- var ch = selectChannel.getStore().getAt(index);
- videoPlayer.zapTo(ch.id);
+ videoPlayer.setResolution(r.data.res);
+ if (videoPlayer.isIdle())
+ return;
+
+ var index = selectChannel.selectedIndex;
+ if (index < 0)
+ return;
+
+ var ch = selectChannel.getStore().getAt(index);
+ videoPlayer.zapTo(ch.id);
});
var win = new Ext.Window({
- title : 'Live TV Player',
- layout : 'fit',
- width : 682 + 14,
- height : 384 + 56,
- constrainHeader : true,
- iconCls : 'eye',
- resizable : true,
- tbar : [
- selectChannel,
- '-',
- {
- iconCls : 'control_play',
- tooltip : 'Play',
- handler : function() {
- if(!videoPlayer.isIdle()) { //probobly paused
- videoPlayer.play();
- return;
- }
-
- var index = selectChannel.selectedIndex;
- if(index < 0)
- return;
-
- var ch = selectChannel.getStore().getAt(index);
- videoPlayer.zapTo(ch.id);
- }
- },
- {
- iconCls : 'control_pause',
- tooltip : 'Pause',
- handler : function() {
- videoPlayer.pause();
- }
- },
- {
- iconCls : 'control_stop',
- tooltip : 'Stop',
- handler : function() {
- videoPlayer.stop();
- }
- },
- '-',
- {
- iconCls : 'control_fullscreen',
- tooltip : 'Fullscreen',
- handler : function() {
- videoPlayer.fullscreen();
- }
- },
- '-',
- selectResolution,
- '-',
- {
- iconCls : 'control_volume',
- tooltip : 'Volume',
- disabled : true
- }, ],
- items : [videoPlayer]
+ title: 'Live TV Player',
+ layout: 'fit',
+ width: 682 + 14,
+ height: 384 + 56,
+ constrainHeader: true,
+ iconCls: 'eye',
+ resizable: true,
+ tbar: [
+ selectChannel,
+ '-',
+ {
+ iconCls: 'control_play',
+ tooltip: 'Play',
+ handler: function() {
+ if (!videoPlayer.isIdle()) { //probobly paused
+ videoPlayer.play();
+ return;
+ }
+
+ var index = selectChannel.selectedIndex;
+ if (index < 0)
+ return;
+
+ var ch = selectChannel.getStore().getAt(index);
+ videoPlayer.zapTo(ch.id);
+ }
+ },
+ {
+ iconCls: 'control_pause',
+ tooltip: 'Pause',
+ handler: function() {
+ videoPlayer.pause();
+ }
+ },
+ {
+ iconCls: 'control_stop',
+ tooltip: 'Stop',
+ handler: function() {
+ videoPlayer.stop();
+ }
+ },
+ '-',
+ {
+ iconCls: 'control_fullscreen',
+ tooltip: 'Fullscreen',
+ handler: function() {
+ videoPlayer.fullscreen();
+ }
+ },
+ '-',
+ selectResolution,
+ '-',
+ {
+ iconCls: 'control_volume',
+ tooltip: 'Volume',
+ disabled: true
+ }],
+ items: [videoPlayer]
});
-
+
win.on('beforeShow', function() {
- win.getTopToolbar().add(slider);
- win.getTopToolbar().add(new Ext.Toolbar.Spacer());
- win.getTopToolbar().add(new Ext.Toolbar.Spacer());
- win.getTopToolbar().add(new Ext.Toolbar.Spacer());
- win.getTopToolbar().add(sliderLabel);
+ win.getTopToolbar().add(slider);
+ win.getTopToolbar().add(new Ext.Toolbar.Spacer());
+ win.getTopToolbar().add(new Ext.Toolbar.Spacer());
+ win.getTopToolbar().add(new Ext.Toolbar.Spacer());
+ win.getTopToolbar().add(sliderLabel);
});
-
+
win.on('close', function() {
- videoPlayer.stop();
+ videoPlayer.stop();
});
win.show();
* Obviosuly, access is verified in the server too.
*/
function accessUpdate(o) {
- tvheadend.accessUpdate = o;
- if (!tvheadend.capabilities)
- return;
-
- if (o.dvr == true && tvheadend.dvrpanel == null) {
- tvheadend.dvrpanel = new tvheadend.dvr;
- tvheadend.rootTabPanel.add(tvheadend.dvrpanel);
- }
-
- if (o.admin == true && tvheadend.confpanel == null) {
- var tabs1 = [
- new tvheadend.miscconf,
- new tvheadend.acleditor
- ]
- var tabs2;
-
- /* DVB inputs */
- tabs2 = [];
- if (tvheadend.capabilities.indexOf('linuxdvb') != -1 ||
- tvheadend.capabilities.indexOf('v4l') != -1) {
- tabs2.push(new tvheadend.tvadapters);
- }
-/*
- tabs2.push(new tvheadend.iptv);
-*/
- tvheadend.conf_dvbin = new Ext.TabPanel({
- activeTab: 0,
- autoScroll: true,
- title: 'DVB Inputs',
- iconCls: 'hardware',
- items : tabs2
- });
- tvheadend.networks(tvheadend.conf_dvbin);
- tvheadend.muxes(tvheadend.conf_dvbin);
- tvheadend.services(tvheadend.conf_dvbin);
- tvheadend.mux_sched(tvheadend.conf_dvbin);
- tabs1.push(tvheadend.conf_dvbin);
-
- /* Channel / EPG */
- tvheadend.conf_chepg = new Ext.TabPanel({
- activeTab: 0,
- autoScroll: true,
- title : 'Channel / EPG',
- iconCls : 'television',
- items : [
- new tvheadend.cteditor,
- new tvheadend.epggrab
- ]
- });
- tvheadend.channel_tab(tvheadend.conf_chepg);
- tabs1.push(tvheadend.conf_chepg);
+ tvheadend.accessUpdate = o;
+ if (!tvheadend.capabilities)
+ return;
- /* DVR / Timeshift */
- tabs2 = [ new tvheadend.dvrsettings ];
- if (tvheadend.capabilities.indexOf('timeshift') != -1) {
- tabs2.push(new tvheadend.timeshift)
+ if (o.dvr == true && tvheadend.dvrpanel == null) {
+ tvheadend.dvrpanel = new tvheadend.dvr;
+ tvheadend.rootTabPanel.add(tvheadend.dvrpanel);
}
- tvheadend.conf_tsdvr = new Ext.TabPanel({
- activeTab: 0,
- autoScroll: true,
- title: 'Recording',
- iconCls: 'drive',
- items : tabs2
- });
- tabs1.push(tvheadend.conf_tsdvr);
-
- /* CSA */
- if (tvheadend.capabilities.indexOf('cwc') != -1) {
- tvheadend.conf_csa = new Ext.TabPanel({
- activeTab: 0,
- autoScroll: true,
- title: 'CSA',
- iconCls: 'key',
- items: [
- new tvheadend.cwceditor,
- new tvheadend.capmteditor
- ]
- });
- tabs1.push(tvheadend.conf_csa);
+
+ if (o.admin == true && tvheadend.confpanel == null) {
+ var tabs1 = [
+ new tvheadend.miscconf,
+ new tvheadend.acleditor
+ ];
+ var tabs2;
+
+ /* DVB inputs */
+ tabs2 = [];
+ if (tvheadend.capabilities.indexOf('linuxdvb') !== -1 ||
+ tvheadend.capabilities.indexOf('v4l') !== -1) {
+ tabs2.push(new tvheadend.tvadapters);
+ }
+ /*
+ tabs2.push(new tvheadend.iptv);
+ */
+ tvheadend.conf_dvbin = new Ext.TabPanel({
+ activeTab: 0,
+ autoScroll: true,
+ title: 'DVB Inputs',
+ iconCls: 'hardware',
+ items: tabs2
+ });
+ tvheadend.networks(tvheadend.conf_dvbin);
+ tvheadend.muxes(tvheadend.conf_dvbin);
+ tvheadend.services(tvheadend.conf_dvbin);
+ tvheadend.mux_sched(tvheadend.conf_dvbin);
+ tabs1.push(tvheadend.conf_dvbin);
+
+ /* Channel / EPG */
+ tvheadend.conf_chepg = new Ext.TabPanel({
+ activeTab: 0,
+ autoScroll: true,
+ title: 'Channel / EPG',
+ iconCls: 'television',
+ items: [
+ new tvheadend.cteditor,
+ new tvheadend.epggrab
+ ]
+ });
+ tvheadend.channel_tab(tvheadend.conf_chepg);
+ tabs1.push(tvheadend.conf_chepg);
+
+ /* DVR / Timeshift */
+ tabs2 = [new tvheadend.dvrsettings];
+ if (tvheadend.capabilities.indexOf('timeshift') !== -1) {
+ tabs2.push(new tvheadend.timeshift);
+ }
+ tvheadend.conf_tsdvr = new Ext.TabPanel({
+ activeTab: 0,
+ autoScroll: true,
+ title: 'Recording',
+ iconCls: 'drive',
+ items: tabs2
+ });
+ tabs1.push(tvheadend.conf_tsdvr);
+
+ /* CSA */
+ if (tvheadend.capabilities.indexOf('cwc') !== -1) {
+ tvheadend.conf_csa = new Ext.TabPanel({
+ activeTab: 0,
+ autoScroll: true,
+ title: 'CSA',
+ iconCls: 'key',
+ items: [
+ new tvheadend.cwceditor,
+ new tvheadend.capmteditor
+ ]
+ });
+ tabs1.push(tvheadend.conf_csa);
+ }
+
+ /* Stream Config */
+ tvheadend.conf_stream = new Ext.TabPanel({
+ activeTab: 0,
+ autoScroll: true,
+ title: 'Stream',
+ iconCls: 'stream_config',
+ items: []
+ });
+ tvheadend.esfilter_tab(tvheadend.conf_stream);
+ tabs1.push(tvheadend.conf_stream);
+
+ /* Debug */
+ tabs1.push(new tvheadend.tvhlog);
+
+ tvheadend.confpanel = new Ext.TabPanel({
+ activeTab: 0,
+ autoScroll: true,
+ title: 'Configuration',
+ iconCls: 'wrench',
+ items: tabs1
+ });
+
+ tvheadend.rootTabPanel.add(tvheadend.confpanel);
+ tvheadend.confpanel.doLayout();
}
- /* Stream Config */
- tvheadend.conf_stream = new Ext.TabPanel({
- activeTab: 0,
- autoScroll: true,
- title: 'Stream',
- iconCls: 'stream_config',
- items: []
- });
- tvheadend.esfilter_tab(tvheadend.conf_stream);
- tabs1.push(tvheadend.conf_stream);
-
- /* Debug */
- tabs1.push(new tvheadend.tvhlog);
-
- tvheadend.confpanel = new Ext.TabPanel({
- activeTab : 0,
- autoScroll : true,
- title : 'Configuration',
- iconCls : 'wrench',
- items : tabs1
- });
+ if (o.admin == true && tvheadend.statuspanel == null) {
+ tvheadend.statuspanel = new tvheadend.status;
+ tvheadend.rootTabPanel.add(tvheadend.statuspanel);
+ }
- tvheadend.rootTabPanel.add(tvheadend.confpanel);
- tvheadend.confpanel.doLayout();
- }
-
- if (o.admin == true && tvheadend.statuspanel == null) {
- tvheadend.statuspanel = new tvheadend.status;
- tvheadend.rootTabPanel.add(tvheadend.statuspanel);
- }
-
- if (tvheadend.aboutPanel == null) {
- tvheadend.aboutPanel = new Ext.Panel({
- border : false,
- layout : 'fit',
- title : 'About',
- iconCls : 'info',
- autoLoad : 'about.html'
- });
- tvheadend.rootTabPanel.add(tvheadend.aboutPanel);
- }
+ if (tvheadend.aboutPanel == null) {
+ tvheadend.aboutPanel = new Ext.Panel({
+ border: false,
+ layout: 'fit',
+ title: 'About',
+ iconCls: 'info',
+ autoLoad: 'about.html'
+ });
+ tvheadend.rootTabPanel.add(tvheadend.aboutPanel);
+ }
- tvheadend.rootTabPanel.doLayout();
+ tvheadend.rootTabPanel.doLayout();
}
/**
*
*/
function setServerIpPort(o) {
- tvheadend.serverIp = o.ip;
- tvheadend.serverPort = o.port;
+ tvheadend.serverIp = o.ip;
+ tvheadend.serverPort = o.port;
}
function makeRTSPprefix() {
- return 'rtsp://' + tvheadend.serverIp + ':' + tvheadend.serverPort + '/';
+ return 'rtsp://' + tvheadend.serverIp + ':' + tvheadend.serverPort + '/';
}
/**
*
*/
tvheadend.log = function(msg, style) {
- s = style ? '<div style="' + style + '">' : '<div>'
+ s = style ? '<div style="' + style + '">' : '<div>';
- sl = Ext.get('systemlog');
- e = Ext.DomHelper.append(sl, s + '<pre>' + msg + '</pre></div>');
- e.scrollIntoView('systemlog');
-}
+ sl = Ext.get('systemlog');
+ e = Ext.DomHelper.append(sl, s + '<pre>' + msg + '</pre></div>');
+ e.scrollIntoView('systemlog');
+};
/**
*
//create application
tvheadend.app = function() {
- // public space
- return {
-
- // public methods
- init : function() {
- var header = new Ext.Panel({
- split: true,
- region: 'north',
- height : 45,
- boxMaxHeight : 45,
- boxMinHeight : 45,
- border: false,
- hidden: true,
- html: '<div id="header"><h1>Tvheadend Web-Panel</h1></div>'
- });
-
- tvheadend.rootTabPanel = new Ext.TabPanel({
- region : 'center',
- activeTab : 0,
- items : [ new tvheadend.epg ]
- });
-
- var viewport = new Ext.Viewport({
- layout : 'border',
- items : [{
- region : 'south',
- contentEl : 'systemlog',
- split : true,
- autoScroll : true,
- height : 150,
- minSize : 100,
- maxSize : 400,
- collapsible : true,
- collapsed : true,
- title : 'System log',
- margins : '0 0 0 0',
- tools : [ {
- id : 'gear',
- qtip : 'Enable debug output',
- handler : function(event, toolEl, panel) {
- Ext.Ajax.request({
- url : 'comet/debug',
- params : {
- boxid : tvheadend.boxid
- }
- });
- }
- } ]
- }, tvheadend.rootTabPanel, header ]
- });
-
- tvheadend.comet.on('accessUpdate', accessUpdate);
-
- tvheadend.comet.on('setServerIpPort', setServerIpPort);
-
- tvheadend.comet.on('logmessage', function(m) {
- tvheadend.log(m.logtxt);
- });
-
- new tvheadend.cometPoller;
-
- Ext.QuickTips.init();
-
- // Load the chart library smoothie.js, as used by the bandwidth monitor.
- Ext.Loader.load('static/smoothie.js');
- }
-
- };
+ // public space
+ return {
+ // public methods
+ init: function() {
+ var header = new Ext.Panel({
+ split: true,
+ region: 'north',
+ height: 45,
+ boxMaxHeight: 45,
+ boxMinHeight: 45,
+ border: false,
+ hidden: true,
+ html: '<div id="header"><h1>Tvheadend Web-Panel</h1></div>'
+ });
+
+ tvheadend.rootTabPanel = new Ext.TabPanel({
+ region: 'center',
+ activeTab: 0,
+ items: [new tvheadend.epg]
+ });
+
+ var viewport = new Ext.Viewport({
+ layout: 'border',
+ items: [{
+ region: 'south',
+ contentEl: 'systemlog',
+ split: true,
+ autoScroll: true,
+ height: 150,
+ minSize: 100,
+ maxSize: 400,
+ collapsible: true,
+ collapsed: true,
+ title: 'System log',
+ margins: '0 0 0 0',
+ tools: [{
+ id: 'gear',
+ qtip: 'Enable debug output',
+ handler: function(event, toolEl, panel) {
+ Ext.Ajax.request({
+ url: 'comet/debug',
+ params: {
+ boxid: tvheadend.boxid
+ }
+ });
+ }
+ }]
+ }, tvheadend.rootTabPanel, header]
+ });
+
+ tvheadend.comet.on('accessUpdate', accessUpdate);
+
+ tvheadend.comet.on('setServerIpPort', setServerIpPort);
+
+ tvheadend.comet.on('logmessage', function(m) {
+ tvheadend.log(m.logtxt);
+ });
+
+ new tvheadend.cometPoller;
+
+ Ext.QuickTips.init();
+
+ // Load the chart library smoothie.js, as used by the bandwidth monitor.
+ Ext.Loader.load('static/smoothie.js');
+ }
+
+ };
}(); // end of app
tvheadend.tvhlog = function() {
- /*
- * Basic Config
- */
- var confreader = new Ext.data.JsonReader({
- root : 'config'
- }, [ 'tvhlog_path', 'tvhlog_dbg_syslog', 'tvhlog_trace_on',
- 'tvhlog_debug', 'tvhlog_trace' ]);
+ /*
+ * Basic Config
+ */
+ var confreader = new Ext.data.JsonReader({
+ root: 'config'
+ }, ['tvhlog_path', 'tvhlog_dbg_syslog', 'tvhlog_trace_on',
+ 'tvhlog_debug', 'tvhlog_trace']);
- /* ****************************************************************
- * Form Fields
- * ***************************************************************/
+ /* ****************************************************************
+ * Form Fields
+ * ***************************************************************/
- var tvhlogLogPath = new Ext.form.TextField({
- fieldLabel : 'Debug Log Path',
- name : 'tvhlog_path',
- allowBlank : true,
- width: 400
- });
+ var tvhlogLogPath = new Ext.form.TextField({
+ fieldLabel: 'Debug Log Path',
+ name: 'tvhlog_path',
+ allowBlank: true,
+ width: 400
+ });
- var tvhlogToSyslog = new Ext.form.Checkbox({
- name: 'tvhlog_dbg_syslog',
- fieldLabel: 'Debug to syslog'
- });
-
- var tvhlogTraceOn = new Ext.form.Checkbox({
- name: 'tvhlog_trace_on',
- fieldLabel: 'Debug trace (low-level stuff)'
- });
+ var tvhlogToSyslog = new Ext.form.Checkbox({
+ name: 'tvhlog_dbg_syslog',
+ fieldLabel: 'Debug to syslog'
+ });
- var tvhlogDebugSubsys = new Ext.form.TextField({
- fieldLabel : 'Debug Subsystems',
- name : 'tvhlog_debug',
- allowBlank : true,
- width: 400
- });
+ var tvhlogTraceOn = new Ext.form.Checkbox({
+ name: 'tvhlog_trace_on',
+ fieldLabel: 'Debug trace (low-level stuff)'
+ });
- var tvhlogTraceSubsys = new Ext.form.TextField({
- fieldLabel : 'Trace Subsystems',
- name : 'tvhlog_trace',
- allowBlank : true,
- width: 400
- });
+ var tvhlogDebugSubsys = new Ext.form.TextField({
+ fieldLabel: 'Debug Subsystems',
+ name: 'tvhlog_debug',
+ allowBlank: true,
+ width: 400
+ });
- /* ****************************************************************
- * Form
- * ***************************************************************/
+ var tvhlogTraceSubsys = new Ext.form.TextField({
+ fieldLabel: 'Trace Subsystems',
+ name: 'tvhlog_trace',
+ allowBlank: true,
+ width: 400
+ });
- var saveButton = new Ext.Button({
- text : "Save configuration",
- tooltip : 'Save changes made to configuration below',
- iconCls : 'save',
- handler : saveChanges
- });
+ /* ****************************************************************
+ * Form
+ * ***************************************************************/
- var helpButton = new Ext.Button({
- text : 'Help',
- handler : function() {
- new tvheadend.help('Debug Configuration', 'config_tvhlog.html');
- }
- });
+ var saveButton = new Ext.Button({
+ text: "Save configuration",
+ tooltip: 'Save changes made to configuration below',
+ iconCls: 'save',
+ handler: saveChanges
+ });
- var confpanel = new Ext.form.FormPanel({
- title : 'Debugging',
- iconCls : 'wrench',
- border : false,
- bodyStyle : 'padding:15px',
- labelAlign : 'left',
- labelWidth : 200,
- waitMsgTarget : true,
- reader : confreader,
- layout : 'form',
- defaultType : 'textfield',
- autoHeight : true,
- items : [ tvhlogLogPath, tvhlogToSyslog,
- tvhlogTraceOn, tvhlogDebugSubsys, tvhlogTraceSubsys ],
- tbar : [ saveButton, '->', helpButton ]
- });
+ var helpButton = new Ext.Button({
+ text: 'Help',
+ handler: function() {
+ new tvheadend.help('Debug Configuration', 'config_tvhlog.html');
+ }
+ });
- /* ****************************************************************
- * Load/Save
- * ***************************************************************/
+ var confpanel = new Ext.form.FormPanel({
+ title: 'Debugging',
+ iconCls: 'wrench',
+ border: false,
+ bodyStyle: 'padding:15px',
+ labelAlign: 'left',
+ labelWidth: 200,
+ waitMsgTarget: true,
+ reader: confreader,
+ layout: 'form',
+ defaultType: 'textfield',
+ autoHeight: true,
+ items: [tvhlogLogPath, tvhlogToSyslog,
+ tvhlogTraceOn, tvhlogDebugSubsys, tvhlogTraceSubsys],
+ tbar: [saveButton, '->', helpButton]
+ });
- confpanel.on('render', function() {
- confpanel.getForm().load({
- url : 'tvhlog',
- params : {
- op : 'loadSettings'
- },
- success : function(form, action) {
- confpanel.enable();
- }
- });
- });
+ /* ****************************************************************
+ * Load/Save
+ * ***************************************************************/
- function saveChanges() {
- confpanel.getForm().submit({
- url : 'tvhlog',
- params : {
- op : 'saveSettings'
- },
- waitMsg : 'Saving Data...',
- failure : function(form, action) {
- Ext.Msg.alert('Save failed', action.result.errormsg);
- }
- });
- }
+ confpanel.on('render', function() {
+ confpanel.getForm().load({
+ url: 'tvhlog',
+ params: {
+ op: 'loadSettings'
+ },
+ success: function(form, action) {
+ confpanel.enable();
+ }
+ });
+ });
- return confpanel;
-}
+ function saveChanges() {
+ confpanel.getForm().submit({
+ url: 'tvhlog',
+ params: {
+ op: 'saveSettings'
+ },
+ waitMsg: 'Saving Data...',
+ failure: function(form, action) {
+ Ext.Msg.alert('Save failed', action.result.errormsg);
+ }
+ });
+ }
+
+ return confpanel;
+};
*/
tvheadend.v4l_adapter_general = function(adapterData) {
- adapterId = adapterData.identifier;
-
- /* Conf panel */
-
- var confreader = new Ext.data.JsonReader({
- root : 'v4ladapters'
- }, [ 'name', 'logging' ]);
-
- function saveConfForm() {
- confform.getForm().submit({
- url : 'v4l/adapter/' + adapterId,
- params : {
- 'op' : 'save'
- },
- waitMsg : 'Saving Data...'
- });
- }
-
- var items = [ {
- fieldLabel : 'Adapter name',
- name : 'name',
- width : 250
- }, new Ext.form.Checkbox({
- fieldLabel : 'Detailed logging',
- name : 'logging'
- }) ];
-
- var confform = new Ext.FormPanel({
- title : 'Adapter configuration',
- columnWidth : .40,
- frame : true,
- border : true,
- disabled : true,
- style : 'margin:10px',
- bodyStyle : 'padding:5px',
- labelAlign : 'right',
- labelWidth : 110,
- waitMsgTarget : true,
- reader : confreader,
- defaultType : 'textfield',
- items : items,
- buttons : [ {
- text : 'Save',
- handler : saveConfForm
- } ]
- });
-
- confform.getForm().load({
- url : 'v4l/adapter/' + adapterId,
- params : {
- 'op' : 'load'
- },
- success : function(form, action) {
- confform.enable();
- }
- });
-
- /**
- * Information / capabilities panel
- */
-
- var infoTemplate = new Ext.XTemplate(
- '<h2 style="font-size: 150%">Hardware</h2>'
- + '<h3>Device path:</h3>{path}' + '<h3>Device name:</h3>{devicename}'
- + '<h2 style="font-size: 150%">Status</h2>'
- + '<h3>Currently tuned to:</h3>{currentMux} ');
-
- var infoPanel = new Ext.Panel({
- title : 'Information and capabilities',
- columnWidth : .35,
- frame : true,
- border : true,
- style : 'margin:10px',
- bodyStyle : 'padding:5px',
- html : infoTemplate.applyTemplate(adapterData)
- });
-
- /**
- * Main adapter panel
- */
- var panel = new Ext.Panel({
- title : 'General',
- layout : 'column',
- items : [ confform, infoPanel ]
- });
-
- /**
- * Subscribe and react on updates for this adapter
- */
- tvheadend.tvAdapterStore.on('update', function(s, r, o) {
- if (r.data.identifier != adapterId) return;
- infoTemplate.overwrite(infoPanel.body, r.data);
- });
-
- return panel;
-}
+ adapterId = adapterData.identifier;
+
+ /* Conf panel */
+
+ var confreader = new Ext.data.JsonReader({
+ root: 'v4ladapters'
+ }, ['name', 'logging']);
+
+ function saveConfForm() {
+ confform.getForm().submit({
+ url: 'v4l/adapter/' + adapterId,
+ params: {
+ 'op': 'save'
+ },
+ waitMsg: 'Saving Data...'
+ });
+ }
+
+ var items = [{
+ fieldLabel: 'Adapter name',
+ name: 'name',
+ width: 250
+ }, new Ext.form.Checkbox({
+ fieldLabel: 'Detailed logging',
+ name: 'logging'
+ })];
+
+ var confform = new Ext.FormPanel({
+ title: 'Adapter configuration',
+ columnWidth: .40,
+ frame: true,
+ border: true,
+ disabled: true,
+ style: 'margin:10px',
+ bodyStyle: 'padding:5px',
+ labelAlign: 'right',
+ labelWidth: 110,
+ waitMsgTarget: true,
+ reader: confreader,
+ defaultType: 'textfield',
+ items: items,
+ buttons: [{
+ text: 'Save',
+ handler: saveConfForm
+ }]
+ });
+
+ confform.getForm().load({
+ url: 'v4l/adapter/' + adapterId,
+ params: {
+ 'op': 'load'
+ },
+ success: function(form, action) {
+ confform.enable();
+ }
+ });
+
+ /**
+ * Information / capabilities panel
+ */
+
+ var infoTemplate = new Ext.XTemplate(
+ '<h2 style="font-size: 150%">Hardware</h2>'
+ + '<h3>Device path:</h3>{path}' + '<h3>Device name:</h3>{devicename}'
+ + '<h2 style="font-size: 150%">Status</h2>'
+ + '<h3>Currently tuned to:</h3>{currentMux} ');
+
+ var infoPanel = new Ext.Panel({
+ title: 'Information and capabilities',
+ columnWidth: .35,
+ frame: true,
+ border: true,
+ style: 'margin:10px',
+ bodyStyle: 'padding:5px',
+ html: infoTemplate.applyTemplate(adapterData)
+ });
+
+ /**
+ * Main adapter panel
+ */
+ var panel = new Ext.Panel({
+ title: 'General',
+ layout: 'column',
+ items: [confform, infoPanel]
+ });
+
+ /**
+ * Subscribe and react on updates for this adapter
+ */
+ tvheadend.tvAdapterStore.on('update', function(s, r, o) {
+ if (r.data.identifier !== adapterId)
+ return;
+ infoTemplate.overwrite(infoPanel.body, r.data);
+ });
+
+ return panel;
+};
/**
* V4L service grid
*/
tvheadend.v4l_services = function(adapterId) {
- var fm = Ext.form;
-
- var enabledColumn = new Ext.grid.CheckColumn({
- header : "Enabled",
- dataIndex : 'enabled',
- width : 45
- });
-
- var cm = new Ext.grid.ColumnModel({
- defaultSortable: true,
- columns : [
- enabledColumn, {
- header : "Channel name",
- dataIndex : 'channelname',
- width : 150,
- renderer : function(value, metadata, record, row, col, store) {
- return value ? value : '<span class="tvh-grid-unset">Unmapped</span>';
- },
- editor : new fm.ComboBox({
- store : tvheadend.channels,
- allowBlank : true,
- typeAhead : true,
- minChars : 2,
- lazyRender : true,
- triggerAction : 'all',
- mode : 'local',
- displayField : 'name'
- })
- }, {
- header : "Frequency",
- dataIndex : 'frequency',
- width : 60,
- editor : new fm.NumberField({
- minValue : 10000,
- maxValue : 1000000000
- })
- } ]});
-
- var rec = Ext.data.Record.create([ 'id', 'enabled', 'channelname',
- 'frequency' ]);
-
- var store = new Ext.data.JsonStore({
- root : 'entries',
- fields : rec,
- url : "v4l/services/" + adapterId,
- autoLoad : true,
- id : 'id',
- baseParams : {
- op : "get"
- },
- listeners : {
- 'update' : function(s, r, o) {
- d = s.getModifiedRecords().length == 0
- saveBtn.setDisabled(d);
- rejectBtn.setDisabled(d);
- }
- }
- });
-
- function addRecord() {
- Ext.Ajax.request({
- url : "v4l/services/" + adapterId,
- params : {
- op : "create"
- },
- failure : function(response, options) {
- Ext.MessageBox.alert('Server Error',
- 'Unable to generate new record');
- },
- success : function(response, options) {
- var responseData = Ext.util.JSON.decode(response.responseText);
- var p = new rec(responseData, responseData.id);
- grid.stopEditing();
- store.insert(0, p);
- grid.startEditing(0, 0);
- }
- })
- }
- ;
-
- function delSelected() {
- var selectedKeys = grid.selModel.selections.keys;
- if (selectedKeys.length > 0) {
- Ext.MessageBox.confirm('Message',
- 'Do you really want to delete selection?', deleteRecord);
- }
- else {
- Ext.MessageBox.alert('Message',
- 'Please select at least one item to delete');
- }
- }
- ;
-
- function deleteRecord(btn) {
- if (btn == 'yes') {
- var selectedKeys = grid.selModel.selections.keys;
-
- Ext.Ajax.request({
- url : "v4l/services/" + adapterId,
- params : {
- op : "delete",
- entries : Ext.encode(selectedKeys)
- },
- failure : function(response, options) {
- Ext.MessageBox.alert('Server Error', 'Unable to delete');
- },
- success : function(response, options) {
- store.reload();
- }
- })
- }
- }
-
- function saveChanges() {
- var mr = store.getModifiedRecords();
- var out = new Array();
- for ( var x = 0; x < mr.length; x++) {
- v = mr[x].getChanges();
- out[x] = v;
- out[x].id = mr[x].id;
- }
-
- Ext.Ajax.request({
- url : "v4l/services/" + adapterId,
- params : {
- op : "update",
- entries : Ext.encode(out)
- },
- success : function(response, options) {
- store.commitChanges();
- },
- failure : function(response, options) {
- Ext.MessageBox.alert('Message', response.statusText);
- }
- });
- }
-
- var delButton = new Ext.Toolbar.Button({
- tooltip : 'Delete one or more selected rows',
- iconCls : 'remove',
- text : 'Delete selected services',
- handler : delSelected,
- disabled : true
- });
-
- var saveBtn = new Ext.Toolbar.Button({
- tooltip : 'Save any changes made (Changed cells have red borders).',
- iconCls : 'save',
- text : "Save changes",
- handler : saveChanges,
- disabled : true
- });
-
- var rejectBtn = new Ext.Toolbar.Button({
- tooltip : 'Revert any changes made (Changed cells have red borders).',
- iconCls : 'undo',
- text : "Revert changes",
- handler : function() {
- store.rejectChanges();
- },
- disabled : true
- });
-
- var selModel = new Ext.grid.RowSelectionModel({
- singleSelect : false
- });
-
- var grid = new Ext.grid.EditorGridPanel({
- stripeRows : true,
- title : 'Services',
- plugins : [ enabledColumn ],
- store : store,
- clicksToEdit : 2,
- cm : cm,
- viewConfig : {
- forceFit : true
- },
- selModel : selModel,
- tbar : [
- {
- tooltip : 'Create a new entry on the server. '
- + 'The new entry is initially disabled so it must be enabled '
- + 'before it start taking effect.',
- iconCls : 'add',
- text : 'Add service',
- handler : addRecord
- }, '-', delButton, '-', saveBtn, rejectBtn ]
- });
-
- store.on('update', function(s, r, o) {
- d = s.getModifiedRecords().length == 0
- saveBtn.setDisabled(d);
- rejectBtn.setDisabled(d);
- });
-
- selModel.on('selectionchange', function(self) {
- delButton.setDisabled(self.getCount() == 0);
- });
-
- return grid;
-}
+ var fm = Ext.form;
+
+ var enabledColumn = new Ext.grid.CheckColumn({
+ header: "Enabled",
+ dataIndex: 'enabled',
+ width: 45
+ });
+
+ var cm = new Ext.grid.ColumnModel({
+ defaultSortable: true,
+ columns: [
+ enabledColumn, {
+ header: "Channel name",
+ dataIndex: 'channelname',
+ width: 150,
+ renderer: function(value, metadata, record, row, col, store) {
+ return value ? value : '<span class="tvh-grid-unset">Unmapped</span>';
+ },
+ editor: new fm.ComboBox({
+ store: tvheadend.channels,
+ allowBlank: true,
+ typeAhead: true,
+ minChars: 2,
+ lazyRender: true,
+ triggerAction: 'all',
+ mode: 'local',
+ displayField: 'name'
+ })
+ }, {
+ header: "Frequency",
+ dataIndex: 'frequency',
+ width: 60,
+ editor: new fm.NumberField({
+ minValue: 10000,
+ maxValue: 1000000000
+ })
+ }]});
+
+ var rec = Ext.data.Record.create(['id', 'enabled', 'channelname',
+ 'frequency']);
+
+ var store = new Ext.data.JsonStore({
+ root: 'entries',
+ fields: rec,
+ url: "v4l/services/" + adapterId,
+ autoLoad: true,
+ id: 'id',
+ baseParams: {
+ op: "get"
+ },
+ listeners: {
+ 'update': function(s, r, o) {
+ d = s.getModifiedRecords().length === 0;
+ saveBtn.setDisabled(d);
+ rejectBtn.setDisabled(d);
+ }
+ }
+ });
+
+ function addRecord() {
+ Ext.Ajax.request({
+ url: "v4l/services/" + adapterId,
+ params: {
+ op: "create"
+ },
+ failure: function(response, options) {
+ Ext.MessageBox.alert('Server Error',
+ 'Unable to generate new record');
+ },
+ success: function(response, options) {
+ var responseData = Ext.util.JSON.decode(response.responseText);
+ var p = new rec(responseData, responseData.id);
+ grid.stopEditing();
+ store.insert(0, p);
+ grid.startEditing(0, 0);
+ }
+ });
+ };
+
+ function delSelected() {
+ var selectedKeys = grid.selModel.selections.keys;
+ if (selectedKeys.length > 0) {
+ Ext.MessageBox.confirm('Message',
+ 'Do you really want to delete selection?', deleteRecord);
+ }
+ else {
+ Ext.MessageBox.alert('Message',
+ 'Please select at least one item to delete');
+ }
+ };
+
+ function deleteRecord(btn) {
+ if (btn === 'yes') {
+ var selectedKeys = grid.selModel.selections.keys;
+
+ Ext.Ajax.request({
+ url: "v4l/services/" + adapterId,
+ params: {
+ op: "delete",
+ entries: Ext.encode(selectedKeys)
+ },
+ failure: function(response, options) {
+ Ext.MessageBox.alert('Server Error', 'Unable to delete');
+ },
+ success: function(response, options) {
+ store.reload();
+ }
+ });
+ }
+ }
+
+ function saveChanges() {
+ var mr = store.getModifiedRecords();
+ var out = new Array();
+ for (var x = 0; x < mr.length; x++) {
+ v = mr[x].getChanges();
+ out[x] = v;
+ out[x].id = mr[x].id;
+ }
+
+ Ext.Ajax.request({
+ url: "v4l/services/" + adapterId,
+ params: {
+ op: "update",
+ entries: Ext.encode(out)
+ },
+ success: function(response, options) {
+ store.commitChanges();
+ },
+ failure: function(response, options) {
+ Ext.MessageBox.alert('Message', response.statusText);
+ }
+ });
+ }
+
+ var delButton = new Ext.Toolbar.Button({
+ tooltip: 'Delete one or more selected rows',
+ iconCls: 'remove',
+ text: 'Delete selected services',
+ handler: delSelected,
+ disabled: true
+ });
+
+ var saveBtn = new Ext.Toolbar.Button({
+ tooltip: 'Save any changes made (Changed cells have red borders).',
+ iconCls: 'save',
+ text: "Save changes",
+ handler: saveChanges,
+ disabled: true
+ });
+
+ var rejectBtn = new Ext.Toolbar.Button({
+ tooltip: 'Revert any changes made (Changed cells have red borders).',
+ iconCls: 'undo',
+ text: "Revert changes",
+ handler: function() {
+ store.rejectChanges();
+ },
+ disabled: true
+ });
+
+ var selModel = new Ext.grid.RowSelectionModel({
+ singleSelect: false
+ });
+
+ var grid = new Ext.grid.EditorGridPanel({
+ stripeRows: true,
+ title: 'Services',
+ plugins: [enabledColumn],
+ store: store,
+ clicksToEdit: 2,
+ cm: cm,
+ viewConfig: {
+ forceFit: true
+ },
+ selModel: selModel,
+ tbar: [
+ {
+ tooltip: 'Create a new entry on the server. '
+ + 'The new entry is initially disabled so it must be enabled '
+ + 'before it start taking effect.',
+ iconCls: 'add',
+ text: 'Add service',
+ handler: addRecord
+ }, '-', delButton, '-', saveBtn, rejectBtn]
+ });
+
+ store.on('update', function(s, r, o) {
+ d = s.getModifiedRecords().length === 0;
+ saveBtn.setDisabled(d);
+ rejectBtn.setDisabled(d);
+ });
+
+ selModel.on('selectionchange', function(self) {
+ delButton.setDisabled(self.getCount() === 0);
+ });
+
+ return grid;
+};
/**
*
*/
tvheadend.v4l_adapter = function(data) {
- var panel = new Ext.TabPanel({
- border : false,
- activeTab : 0,
- autoScroll : true,
- items : [ new tvheadend.v4l_adapter_general(data),
- new tvheadend.v4l_services(data.identifier) ]
- });
- return panel;
-}
+ var panel = new Ext.TabPanel({
+ border: false,
+ activeTab: 0,
+ autoScroll: true,
+ items: [new tvheadend.v4l_adapter_general(data),
+ new tvheadend.v4l_services(data.identifier)]
+ });
+ return panel;
+};