WebIf: Add a second style "light" style which uses a lot of light grey as background...
[enigma2-plugins.git] / webinterface / src / web-data / core.js
1 var Controller = Class.create({
2         initialize: function(handler){
3                 this.handler = handler;
4                 this.handler.onFinished.push(this.registerEvents.bind(this));
5                 this.handler.onFinished.push(this.onFinished.bind(this));
6                 this.eventsregistered = false;
7         },
8
9         registerEvents: function(){
10                 this.eventsregistered = true;
11         },
12
13         onFinished: function(){}
14 });
15
16 var Bouquets = Class.create(Controller, {
17         initialize: function($super, targetBouquets, targetMain){
18                 $super(new BouquetListHandler(targetBouquets, targetMain));
19                 this.loadFirstOnFinished = false;
20         },
21
22         load: function(sRef, loadFirstOnFinished){
23                 if(loadFirstOnFinished)
24                         this.loadFirstOnFinished = true;
25                 this.handler.load( {'sRef' : sRef} );
26                 var services = $('contentServices');
27                 if(services){
28                         services.update(strings.select_bouquet);
29                 }
30         },
31
32         loadBouquetsTv: function(){
33                 setContentHd(strings.bouquets + ' (' + strings.tv + ')');
34                 this.load(bouquetsTv);
35         },
36
37         loadProviderTv: function(){
38                 setContentHd(strings.providers + ' (' + strings.tv + ')');
39                 this.load(providerTv);
40         },
41
42         loadSatellitesTv: function(){
43                 setContentHd(strings.satellites + ' (' + strings.tv + ')');
44                 this.load(satellitesTv);
45         },
46
47         loadBouquetsRadio: function(){
48                 setContentHd(strings.bouquets + ' (' + strings.radio + ')');
49                 this.load(bouquetsRadio);
50         },
51
52         loadProviderRadio: function(){
53                 setContentHd(strings.providers + ' (' + strings.radio + ')');
54                 this.load(providerRadio);
55         },
56
57         loadSatellitesRadio: function(){
58                 setContentHd(strings.satellites + ' (' + strings.radio + ')');
59                 this.load(satellitesRadio);
60         },
61
62         onFinished: function(){
63                 var bouquets = this.handler.data.services;
64                 if(bouquets){
65                         if(this.loadFirstOnFinished || bouquets.length == 1){
66                                 var bouquet = bouquets[0];
67                                 setContentHd(bouquet.servicename);
68                                 this.loadFirstOnFinished = false;
69                                 hash = core.getBaseHash() + '/' + bouquet.servicereference;
70                                 hashListener.setHash(hash);
71                         } else {
72                                 var currentBouquet = hashListener.getHash().split('/')[3];
73                                 if(currentBouquet){
74                                         bouquets.each(function(bouquet){
75                                                 if(bouquet.servicereference == currentBouquet){
76                                                         setContentHd(bouquet.servicename);
77                                                 }
78                                         });
79                                 }
80                         }
81                 }
82         }
83 });
84
85 var Current = Class.create(Controller, {
86         initialize: function($super, curTarget, volTarget){
87                 $super(new CurrentHandler(curTarget, volTarget));
88                 this.handler.onFinished[this.handler.onFinished.length] = this.onFinished.bind(this);
89                 this.display = 'none';
90         },
91
92         load: function(){
93                 this.handler.load({});
94         },
95
96         toggleVisibility: function(element){
97                 var ext = $('trExtCurrent');
98                 if(ext){
99                         var bullet = element.down('.currentBulletToggle');
100                         if(ext.visible()){
101                                 bullet.src = '/web-data/img/toggle_expand.png';
102                                 bullet.alt = "+";
103                                 ext.hide();
104                         }else{
105                                 bullet.src = '/web-data/img/toggle_collapse.png';
106                                 bullet.alt = "-";
107                                 ext.show();
108                         }
109                         this.display = ext.style.display;
110                         setMaxHeight('contentMain');
111                 }
112         },
113
114         onFinished: function(){
115                 setMaxHeight('contentMain');
116                 var ext = $('trExtCurrent');
117                 if(ext){
118                         ext.style.display = this.display;
119                         var bullet = $('currentName').down('.currentBulletToggle');
120                         if(ext.visible()){
121                                 bullet.src = '/web-data/img/toggle_collapse.png';
122                                 bullet.alt = "-";
123                         }else{
124                                 bullet.src = '/web-data/img/toggle_expand.png';
125                                 bullet.alt = "+";
126                         }
127                 }
128                 core.currentData = this.handler.data;
129         }
130 });
131
132 var Externals = Class.create(Controller, {
133         initialize: function($super, target){
134                 $super(new ExternalsHandler(target));
135                 this.loaded = false;
136         },
137
138         load: function(){
139                 if(!this.loaded)
140                         this.handler.load({});
141                 else
142                         this.handler.show(this.handler.data);
143         },
144
145         onFinished: function(){
146                 this.loaded = true;
147         }
148 });
149
150 var EPG = Class.create(Controller, {
151         initialize: function($super){
152                 $super(new EpgListHandler(this.show.bind(this)));
153                 this.window = '';
154         },
155
156         show:function(html){
157                 var win = core.popup("EPG" + new Date().getTime(), html, 900, 500);
158                 this.doRegisterEvents(win);
159         },
160
161         load: function(sRef){
162                 this.handler.load({'sRef' : sRef});
163         },
164
165         search: function(needle){
166                 this.handler.search({'search' : needle});
167         },
168
169         doRegisterEvents: function(win){
170                 var elem = win.document;
171                 var onload = function(event){
172                         elem.on(
173                                 'click',
174                                 '.eListAddTimer',
175                                 function(event, element){
176                                         core.timers.addByEventId(element, 0);
177                                         return false;
178                                 }
179                         );
180                         elem.on(
181                                 'click',
182                                 '.eListZapTimer',
183                                 function(event, element){
184                                         core.timers.addByEventId(element, 1);
185                                         return false;
186                                 }
187                         );
188                         elem.on(
189                                 'click',
190                                 '.eListEditTimer',
191                                 function(event, element){
192                                         var hash = ["#!/timer", "edit"].join("/");
193                                         hashListener.setHash(hash);
194                                         core.timers.editFromEvent(element);
195                                         //return false;
196                                 }
197                         );
198                 };
199                 if(elem.on){
200                         onload();
201                 } else {
202                         win.onload = onload;
203                 }
204         }
205 });
206
207 var MultiEpg = Class.create(Controller, {
208         initialize: function($super){
209                 $super(new MultiEpgHandler(this.show.bind(this)));
210                 this.tplDetails = "";
211         },
212
213         load: function(bRef){
214                 templateEngine.fetch(
215                         'tplMultiEpgDetail',
216                         function(tpl){
217                                 this.tplDetails = tpl;
218                                 this.doLoad(bRef);
219                         }.bind(this));
220         },
221
222         doLoad: function(bRef){
223                 this.handler.load({'bRef' : bRef});
224         },
225
226         show: function(html){
227                 var win = core.popup("MultiEpg" + new Date().getTime(), html, 900, 570);
228                 this.doRegisterEvents(win);
229         },
230
231         doRegisterEvents: function(win){
232                 var elem = win.document;
233                 var _this = this;
234                 var onload = function(event){
235                         elem.on(
236                                 'click',
237                                 '.mEpgItem',
238                                 function(event, element){
239                                         var detail = elem.getElementById('mEpgDetail');
240                                         if(detail){
241                                                 var e = {};
242                                                 e.servicereference = element.readAttribute('data-servicereference');
243                                                 e.servicename = element.readAttribute('data-servicename');
244                                                 e.eventid = element.readAttribute('data-eventid');
245                                                 e.date = element.readAttribute('data-date');
246                                                 e.start = element.readAttribute('data-start');
247                                                 e.starttime = element.readAttribute('data-starttime');
248                                                 e.end = element.readAttribute('data-end');
249                                                 e.endtime = element.readAttribute('data-endtime');
250                                                 e.duration = element.readAttribute('data-duration');
251                                                 e.title = element.readAttribute('data-title');
252                                                 e.description = element.readAttribute('data-description');
253                                                 e.extdescription = element.readAttribute('data-extdescription');
254                                                 var data = {'e' : e};
255                                                 detail.update(_this.tplDetails.process(data));
256                                                 detail.fadeIn({'delay' : 300, 'to' : 95});
257                                         }
258                                         event.stop();
259                                 }
260                         );
261                         elem.on(
262                                 'click',
263                                 '.close',
264                                 function(event, element){
265                                         var detail = elem.getElementById('mEpgDetail');
266                                         if(detail)
267                                                 detail.hide();
268                                         event.stop();
269                                 }
270                         );
271
272                         elem.on(
273                                 'click',
274                                 '.eListAddTimer',
275                                 function(event, element){
276                                         core.timers.addByEventId(element, 0);
277                                         event.stop();
278                                 }
279                         );
280                         elem.on(
281                                 'click',
282                                 '.eListZapTimer',
283                                 function(event, element){
284                                         core.timers.addByEventId(element, 1);
285                                         event.stop();
286                                 }
287                         );
288                         elem.on(
289                                 'click',
290                                 '.eListEditTimer',
291                                 function(event, element){
292                                         var hash = ["#!/timer", "edit"].join("/");
293                                         hashListener.setHash(hash);
294                                         core.timers.editFromEvent(element);
295                                         event.stop();
296                                 }
297                         );
298                 };
299                 if(elem.on){
300                         if(elem.onload)
301                                 elem.onload();
302                         onload();
303                 } else {
304                         win.onload = onload;
305                 }
306         }
307 });
308
309 var Power = Class.create({
310         STATES: {'toggle' : 0, 'deep' : 1, 'reboot' : 2, 'gui' : 3},
311
312         initialize: function(){
313                 //As we do not have an real templates here, there is no handler for powerstate.
314                 //The Handling is up to the caller of this class
315                 this.provider = new PowerstateProvider(this.onLoadFinished.bind(this));
316                 this.callbacks = [];
317                 this.isLoading = false;
318                 this.isStandby = false;
319         },
320
321         load: function(params){
322                 this.isLoading = true;
323                 this.provider.load(params);
324         },
325
326         onLoadFinished:function (isStandby){
327                 this.isStandby = isStandby;
328                 this.isLoading = false;
329                 var len = this.callbacks.length;
330                 for(var i = 0; i < len; i++){
331                         callback = this.callbacks.pop();
332                         callback(this.isStandby);
333                 }
334         },
335
336         inStandby: function(callback){
337                 this.callbacks.push(callback);
338                 if(!this.isLoading){
339                         this.load({});
340                 }
341         },
342
343         set: function(newstate, callback){
344                 this.callbacks.push(callback);
345                 this.load({'newstate' : this.STATES[newstate]});
346         }
347 });
348
349 var LocationsAndTags = Class.create({
350         initialize: function(){
351                 this.currentLocation = '';
352                 this.locations = [];
353                 this.tags = [];
354                 this.isCurrentLocationsLoading = false;
355                 this.isCurrentLocationReady = false;
356                 this.isLocationsLoading = false;
357                 this.isLocationsReady = false;
358                 this.isTagsLoading = false;
359                 this.isTagsReady = false;
360                 this.curLocCallbacks = [];
361                 this.locCallbacks = [];
362                 this.tagCallbacks = [];
363                 this.locTagCallbacks = [];
364
365                 this.curlocprovider = new CurrentLocationProvider(this.onCurrentLocationAvailable.bind(this));
366                 this.locprovider = new LocationProvider(this.onLocationsAvailable.bind(this));
367                 this.tagprovider = new TagProvider(this.onTagsAvailable.bind(this));
368         },
369
370         getCurrentLocation: function(callback){
371                 if(this.isCurrentLocationReady){
372                         callback(this.currentLocation);
373                 } else {
374                         this.curLocCallbacks[this.curLocCallbacks.length] = callback;
375                         if(!this.isCurrentLocationLoading){
376                                 this.curlocprovider.load({});
377                                 this.isCurrentLocationLoading = true;
378                         }
379                 }
380         },
381
382         onCurrentLocationAvailable: function(currentLocation){
383                 debug("[LocationsAndTags].onCurrentLocationAvailable");
384                 this.isCurrentLocationReady = true;
385                 this.isCurrentLocationLoading = false;
386                 this.currentLocation = currentLocation;
387                 var len = this.curLocCallbacks.length;
388                 for(var i = 0; i < len; i++){
389                         callback = this.curLocCallbacks.pop();
390                         callback(this.currentLocation);
391                 }
392                 this.onLocationsOrTagsAvailable();
393         },
394
395         getLocations: function(callback){
396                 if(this.isLocationsReady){
397                         callback(this.locations);
398                 } else {
399                         this.locCallbacks[this.locCallbacks.length] = callback;
400                         if(!this.isLocationsLoading){
401                                 this.locprovider.load({});
402                                 this.isLocationsLoading = true;
403                         }
404                 }
405         },
406
407         onLocationsAvailable: function(locations){
408                 debug("[LocationsAndTags].onLocationsAvailable");
409                 this.isLocationsReady = true;
410                 this.isLocationsLoading = false;
411                 this.locations = locations.getList();
412                 var len = this.locCallbacks.length;
413                 for(var i = 0; i < len; i++){
414                         callback = this.locCallbacks.pop();
415                         callback(this.locations);
416                 }
417                 this.onLocationsOrTagsAvailable();
418         },
419
420         getTags: function(callback){
421                 if(this.isTagsReady){
422                         callback(this.tags);
423                 } else {
424                         this.tagCallbacks[this.tagCallbacks.length] = callback;
425                         if(!this.isTagsLoading){
426                                 this.tagprovider.load({});
427                                 this.isTagsLoading = true;
428                         }
429                 }
430         },
431
432         onTagsAvailable: function(tags){
433                 debug("[LocationsAndTags].onTagsAvailable");
434                 this.isTagsReady = true;
435                 this.isTagsLoading = false;
436                 this.tags = tags.getList();
437                 var len = this.tagCallbacks.length;
438                 for(var i = 0; i < len; i++){
439                         callback = this.tagCallbacks.pop();
440                         callback(this.tags);
441                 }
442                 this.onLocationsOrTagsAvailable();
443         },
444
445         getLocationsAndTags: function(callback){
446                 if(this.isCurrentLocationReady && this.isLocationsReady && this.isTagsReady){
447                         callback(this.currentLocation, this.locations, this.tags);
448                 } else {
449                         this.locTagCallbacks[this.locTagCallbacks.length] = callback;
450                         if(!this.isCurrentLocationLoading)
451                                 this.curlocprovider.load({});
452                         if(!this.isLocationsLoading)
453                                 this.locprovider.load({});
454                         if(!this.isTagsLoading)
455                                 this.tagprovider.load({});
456                 }
457         },
458
459         onLocationsOrTagsAvailable: function(){
460                 if(this.isCurrentLocationReady && this.isLocationsReady && this.isTagsReady){
461                         var len = this.locTagCallbacks.length;
462                         for(var i = 0; i < len; i++){
463                                 callback = this.locTagCallbacks.pop();
464                                 callback(this.currentLocation, this.locations, this.tags);
465                         }
466                 }
467         }
468 });
469
470 var MediaPlayer = Class.create(Controller, {
471         initialize: function($super, target){
472                 $super(new MediaPlayerHandler(target));
473         },
474
475         load: function(path){
476                 if(!path){
477                         path = 'Filesystems';
478                 }
479                 var parms = {'path' : path};
480                 this.handler.load(parms);
481         },
482
483         playFile: function(file){
484                 this.handler.playFile(file);
485         },
486
487         addFile: function(file){
488                 this.handler.addFile(file);
489         },
490
491         removeFile: function(file){
492                 this.handler.removeFile(file);
493         },
494
495         savePlaylist: function(filename){
496                 this.handler.savePlaylist(filename);
497         },
498
499         command: function(cmd){
500                 this.handler.command(cmd);
501         }
502 });
503
504 var Messages = Class.create({
505         initialize: function(){
506                 this.handler = new SimpleRequestHandler();
507         },
508
509         send: function(text, type, timeout){
510                 this.handler.load(URL.message, {'text' : text, 'type' : type, 'timeout' : timeout});
511         }
512 });
513
514 var Movies = Class.create(Controller, {
515         initialize: function($super, listTarget, navTarget, locTarget){
516                 $super(new MovieListHandler(listTarget));
517                 this.navHandler = new MovieNavHandler(navTarget, locTarget);
518         },
519
520         load: function(location, tags){
521                 if(!location){
522                         var sethash = function(location){
523                                 var hash = [core.getBaseHash(), "filter", encodeURIComponent(location), encodeURIComponent(tags)].join("/");
524                                 hashListener.setHash(hash);
525                         };
526                         if(core.currentLocation == ""){ //wait for currentLocation to be set;
527                                 core.lt.getCurrentLocation(sethash);
528                         } else {
529                                 sethash(core.currentLocation);
530                         }
531                         return;
532                 }
533
534                 this.handler.load({'dirname' : location, 'tag' : tags});
535         },
536
537         loadNav: function(){
538                 core.lt.getLocationsAndTags(this.showNav.bind(this));
539         },
540
541         showNav: function(currentLocation, locations, tags){
542                 this.navHandler.load(toOptionList(locations, currentLocation), toOptionList(tags, core.currentTag));
543         },
544
545         del: function(element){
546                 this.handler.del(element);
547         }
548 });
549
550 var RemoteControl = Class.create({
551         initialize: function(){
552                 this.handler = new RemoteControlHandler();
553                 var _this = this;
554                 this.handler.onFinished.push(_this.onKeySent.bind(_this));
555                 this.shotType = '';
556                 this.window = '';
557         },
558
559         open: function(){
560                 if(!this.window)
561                         this.window = '';
562                 if (this.window.closed || !this.window.location){
563                         var tpl;
564                         switch(core.deviceInfo.info.devicename){
565                         case 'dm8000':
566                         case 'dm7020hd':
567                         case 'dm800sev2':
568                         case 'dm500hdv2':
569                                 tpl = 'tplWebRemote';
570                                 break;
571                         default:
572                                 tpl = 'tplWebRemoteOld';
573                         }
574
575                         templateEngine.process(tpl, null, function(html){
576                                 this.eventsregistered = false;
577                                 this.window = core.popup('WebRemote', html, 250, 650);
578                                 this.registerEvents();
579                         }.bind(this));
580                 }
581         },
582
583         sendKey: function(cmd, type, shotType){
584                 debug("[RemoteControl].sendKey: " + cmd);
585                 this.shotType = shotType;
586                 this.handler.sendKey({'command' : cmd, 'type': type});
587
588         },
589
590         onKeySent: function(){
591                 this.screenShot(this.shotType);
592         },
593
594         screenShot: function(shotType){
595                 var hash = '!/control'; //FIXME
596                 switch(shotType){
597                 case 'osd':
598                         hash = [hash, 'osdshot'].join("/");
599                         break;
600                 case 'all':
601                         hash = [hash, 'screenshot'].join("/");
602                         break;
603                 default:
604                         return;
605                 }
606                 //the box needs at least a little bit of time to actually draw the window
607                 //wait 250ms before fetching a new screenshot
608                 setTimeout(
609                         function(){
610                                 var forceReload = hash == hashListener.getHash();
611                                 hashListener.setHash(hash);
612                                 if(forceReload){
613                                         core.onHashChanged(true);
614                                 }
615                         },
616                         250);
617         },
618
619         registerEvents: function(){
620                 var _this = this;
621                 var win = this.window;
622                 var elem = win.document;
623
624                 var onload = function(event){
625                         elem.on(
626                                 'click',
627                                 '.remoteKey',
628                                 function(event, element){
629                                         var id = element.readAttribute('data-keyid');
630                                         var long = _this.window.document.getElementById('long').checked;
631                                         var screenshot = _this.window.document.getElementById('screenshot').checked;
632                                         var video = _this.window.document.getElementById('video').checked;
633                                         var type = '';
634                                         if(long){
635                                                 type = 'long';
636                                         }
637                                         var shotType = '';
638                                         if(screenshot && video){
639                                                 shotType = 'all';
640                                         } else if (screenshot && !video) {
641                                                 shotType = 'osd';
642                                         }
643                                         _this.sendKey(id, type, shotType);
644                                 }
645                         );
646                         elem.on(
647                                 'click',
648                                 '.screenshot',
649                                 function(event, element){
650                                         var video = _this.window.document.getElementById('video').checked;
651                                         var shotType = 'osd';
652                                         if(video)
653                                                 shotType = 'all';
654                                         _this.screenShot(shotType);
655                                 }
656                         );
657                 };
658                 if(elem.on){
659                         onload();
660                 } else {
661                         win.onload = onload;
662                 }
663         }
664 });
665
666 var Screenshots = Class.create(Controller, {
667         TYPE_OSD : 'o',
668         TYPE_VIDEO : 'v',
669         TYPE_ALL : '',
670
671         initialize: function($super, target){
672                 $super(new ScreenshotHandler(target));
673         },
674
675         load: function(type){
676                 var filename = '/tmp/' + new Date().getTime();
677                 var params = {'format' : 'jpg', 'r': '720', 'filename' : filename};
678
679                 switch(type){
680                         case this.TYPE_OSD:
681                                 params['o'] = '';
682                                 params['n'] = '';
683                                 params['format'] = 'png';
684                                 break;
685                         case this.TYPE_VIDEO:
686                                 params['v'] = '';
687                                 break;
688                         default:
689                                 break;
690                 }
691                 this.handler.load(params);
692         },
693
694         shootOsd: function(){
695                 setContentHd(strings.screenshot_osd);
696                 this.load(this.TYPE_OSD);
697         },
698
699         shootVideo: function(){
700                 setContentHd(strings.screenshot_video);
701                 this.load(this.TYPE_VIDEO);
702         },
703
704         shootAll: function(){
705                 setContentHd(strings.screenshot_all);
706                 this.load(this.TYPE_ALL);
707         }
708 });
709
710 var Services = Class.create(Controller, {
711         initialize: function($super, target, epg){
712                 $super(new ServiceListHandler(target));
713                 this.epg = epg;
714                 this.cachedServiceElements = null;
715         },
716
717         zap: function(sRef, callback){
718                 this.handler.zap({'sRef' : sRef}, callback);
719         },
720
721         load: function(sRef){
722                 this.handler.load({'bRef' : sRef});
723         },
724
725         getNowNext: function(){
726                 this.handler.getNowNext();
727         },
728
729         getSubservices: function(){
730                 this.handler.getSubservices();
731         },
732
733         loadAll: function(ref){
734                 var tpl = 'tplBouquetsAndServices';
735                 var fnc = function(){
736                         $('contentBouquets').update(strings.all);
737                         this.load(ref);
738                 }.bind(this);
739
740                 if($('contentBouquets')){
741                         fnc();
742                 } else {
743                         templateEngine.process(
744                                 tpl,
745                                 null,
746                                 'contentMain',
747                                 fnc
748                         );
749                         }
750         },
751
752         loadAllTv: function(){
753                 this.loadAll(allTv);
754                 setContentHd(strings.all + " (" + strings.tv + ")");
755         },
756
757         loadAllRadio: function(){
758                 this.loadAll(allRadio);
759                 setContentHd(strings.all + " (" + strings.radio + ")");
760         },
761
762         onFilterFocus: function(event){
763                 event.element().value = '';
764                 this.cachedServiceElements = null;
765                 this.filter(event);
766         },
767
768         filter: function(event){
769                 var needle = event.element().value.toLowerCase();
770
771                 if(this.cachedServiceElements == null){
772                         this.cachedServiceElements = $$('.sListRow');
773                 }
774                 var cls = 'even';
775                 for(var i = 0; i < this.cachedServiceElements.length; i++){
776                         var row = this.cachedServiceElements[i];
777                         var serviceName = row.readAttribute('data-servicename').toLowerCase();
778
779                         if(serviceName.match(needle) != needle && serviceName != ""){
780                                 row.hide();
781                         } else {
782                                 cls = cls == 'odd' ? 'even' : 'odd';
783                                 notCls = cls == 'odd' ? 'even' : 'odd';
784
785                                 var td = row.firstDescendant();
786                                 td.removeClassName(notCls);
787                                 td.addClassName(cls);
788
789                                 row.show();
790                         }
791                 }
792         },
793
794         addFilterInput: function(){
795                 var input = new Element('input');
796                 input.id = 'serviceFilter';
797                 input.value = strings.filter_services;
798                 $('contentHdExt').update(input);
799                 input.on('focus', this.onFilterFocus.bind(this));
800                 input.on('keyup', this.filter.bind(this));
801         },
802
803         onFinished: function(){
804                 this.addFilterInput();
805                 core.startUpdateBouquetItemsPoller();
806         }
807 });
808
809 var SignalWindow = Class.create(Controller, {
810         initialize: function($super, seconds){
811                 $super(new SignalHandler(this.show.bind(this)));
812                 this.window = '';
813                 if(!isNaN(Number(seconds))){
814                         this.seconds = seconds * 1000;
815                 } else {
816                         this.seconds = 5000;
817                 }
818                 this.interval = '';
819         },
820
821         load: function(){
822                 this.handler.load({});
823         },
824
825         reload: function(){
826                 debug('[SignalWindow].reload');
827                 if (!this.window.closed && this.window.location){
828                         this.load();
829                 } else {
830                         clearInterval(this.interval);
831                 }
832         },
833
834         show: function(html){
835                 debug('[SignalWindow].show');
836                 if (this.window.closed || !this.window.location){
837                         this.window = core.popup("SignalPanel", html, 220, 120);
838                         this.window.onbeforeunload = function(){
839                                 clearInterval(this.interval);
840                         };
841
842                         var _this = this;
843                         clearInterval(_this.interval);
844                         this.interval = setInterval(_this.reload.bind(this), _this.seconds);
845                 } else if(!this.window.closed && this.window.location) {
846                         this.window.document.write(html);
847                         this.window.document.close();
848                 }
849         }
850 });
851
852 var SimplePages = Class.create({
853         PAGE_ABOUT : 'tplAbout',
854         PAGE_MESSAGE : 'tplSendMessage',
855         PAGE_POWER : 'tplPower',
856         PAGE_SETTINGS: 'tplSettings',
857         PAGE_TOOLS: 'tplTools',
858
859         initialize: function(target){
860                 this.simpleHandler = new SimplePageHandler(target);
861                 this.deviceInfoHandler = new DeviceInfoHandler(target);
862         },
863
864         show: function(tpl, data){
865                 if(!data)
866                         data = {};
867                 this.simpleHandler.show(tpl, data);
868         },
869
870         loadAbout: function(){
871                 setContentHd(strings.about);
872                 this.show(this.PAGE_ABOUT);
873         },
874
875         loadMessage: function(){
876                 setContentHd(strings.send_message);
877                 this.show(this.PAGE_MESSAGE);
878         },
879
880         loadPower: function(){
881                 setContentHd(strings.powercontrol);
882                 this.show(this.PAGE_POWER);
883         },
884
885         loadSettings: function(){
886                 setContentHd(strings.settings);
887                 var debug = userprefs.data.debug;
888                 var debugChecked = "";
889                 if(debug){
890                         debugChecked = 'checked';
891                 }
892
893                 var updateCurrentInterval = userprefs.data.updateCurrentInterval / 1000;
894                 var updateBouquetInterval = userprefs.data.updateBouquetInterval / 1000;
895                 var style = userprefs.data.style;
896                 data = {'debug' : debugChecked,
897                                 'updateCurrentInterval' : updateCurrentInterval,
898                                 'updateBouquetInterval' : updateBouquetInterval,
899                                 'style' : style
900                         };
901                 this.show(this.PAGE_SETTINGS, data);
902         },
903
904         loadTools: function(){
905                 setContentHd(strings.tools);
906                 this.show(this.PAGE_TOOLS);
907         },
908
909         loadDeviceInfo: function(){
910                 setContentHd(strings.deviceinfo);
911                 this.deviceInfoHandler.load({});
912         },
913
914         getDeviceInfo: function(callback){
915                 this.deviceInfoHandler.get({}, callback);
916         }
917 });
918
919 var Timers = Class.create({
920         initialize: function(target){
921                 this.listHandler = new TimerListHandler(target);
922                 this.timerHandler = new TimerHandler(target, this.loadList.bind(this), [this.onTimerEditLoadFinished.bind(this)]);
923         },
924
925         loadList: function(){
926                 this.listHandler.load({});
927         },
928
929         cleanupList: function(){
930                 this.listHandler.cleanup();
931         },
932
933         create: function(){
934                 this.timerHandler.load({}, false, true);
935         },
936
937         edit: function(element){
938                 this.timerHandler.load(element, true);
939         },
940
941         editFromEvent: function(element){
942                 this.timerHandler.load(element, false, false, true);
943         },
944
945         save: function(element){
946                 this.timerHandler.commitForm(element);
947         },
948
949         onBouquetChanged: function(bRef){
950                 this.timerHandler.onBouquetChanged(bRef, this.onUpdatedServiceListReady.bind(this));
951         },
952
953         onUpdatedServiceListReady: function(data, timer){
954                 var serviceSel = $('service');
955                 var options = serviceSel.options;
956                 options.length = 0;
957
958                 var i = 0;
959                 data.services.each(function(s){
960                         var selected = false;
961                         if(timer.servicereference == unescape(s.servicereference)){
962                                 selected = true;
963                         }
964                         options.add ( new Option(s.servicename, s.servicereference, false, selected) );
965                         i++;
966                 });
967         },
968
969         recordNow: function(type, callback){
970                 this.timerHandler.recordNow(type, callback);
971         },
972
973         addByEventId: function(element, justplay){
974                 var parent = element.up('.epgListItem');
975                 var sRef = unescape(parent.readAttribute('data-servicereference'));
976                 var eventId = unescape(parent.readAttribute('data-eventid'));
977                 this.timerHandler.addByEventId(sRef, eventId, justplay);
978         },
979
980         toggleDisabled: function(element){
981                 this.timerHandler.toggleDisabled(element);
982         },
983
984         del: function(element){
985                 this.timerHandler.del(element);
986         },
987
988         onTimerEditLoadFinished: function(){
989                 debug("[Timers].onTimerEditLoadFinished");
990                 datePickerController.destroyDatePicker('sdate');
991                 datePickerController.destroyDatePicker('edate');
992                 var today = new Date();
993                 var pad = function(value, length) {
994                         length = length || 2;
995                         return "0000".substr(0,length - Math.min(String(value).length, length)) + value;
996                 };
997                 var opts = {
998                                 showWeeks: true,
999                                 noFadeEffect: true,
1000                                 rangeLow: today.getFullYear() + "" + pad(today.getMonth()+1) + pad(today.getDate())
1001                         };
1002
1003
1004                 opts['formElements'] = { 'sdate' : 'Y-ds-m-ds-d'};
1005                 datePickerController.createDatePicker(opts);
1006
1007                 opts['formElements'] = { 'edate' : 'Y-ds-m-ds-d'};
1008                 datePickerController.createDatePicker(opts);
1009
1010         }
1011 });
1012
1013 var Volume = Class.create(Controller, {
1014         initialize: function($super, target){
1015                 $super(new VolumeHandler(target));
1016         },
1017
1018         load: function(){
1019                 this.handler.load({});
1020         },
1021
1022         set: function(value){
1023                 this.handler.load({'set' : value});
1024         }
1025 });
1026
1027 var E2WebCore = Class.create({
1028         initialize: function(){
1029                 this.mediaPlayerStarted = false;
1030                 this.popUpBlockerHinted = false;
1031                 this.settings = null;
1032                 this.parentControlList = null;
1033
1034                 this.debugWin = '';
1035                 this.signalWin = '';
1036                 this.webRemoteWin = '';
1037                 this.EPGListWin = '';
1038
1039                 this.currentBouquet = bouquetsTv;
1040
1041                 this.updateBouquetItemsPoller = '';
1042                 this.updateCurrentPoller = '';
1043                 this.signalPanelUpdatePoller = '';
1044
1045                 this.hideNotifierTimeout = '';
1046
1047                 this.isActive = {};
1048                 this.isActive.getCurrent = false;
1049
1050                 this.mode = "";
1051                 this.subMode = "";
1052
1053                 //create required Instances
1054                 this.sessionProvider = new SessionProvider( this.onSessionAvailable.bind(this) );
1055
1056                 this.bouquets = new Bouquets('contentBouquets', 'contentMain');
1057                 this.current = new Current('currentContent', 'volContent');
1058                 this.externals = new Externals('navExternalsContainer');
1059                 this.epg = new EPG(new EpgListHandler());
1060                 this.lt = new LocationsAndTags();
1061                 this.mediaplayer = new MediaPlayer('contentMain');
1062                 this.messages = new Messages();
1063                 this.movies = new Movies('contentMain', 'navContent', 'contentHdExt');
1064                 this.multiepg = new MultiEpg();
1065                 this.power = new Power();
1066                 this.remote = new RemoteControl();
1067                 this.screenshots = new Screenshots('contentMain');
1068                 this.services = new Services('contentServices', this.epg);
1069                 this.signal = new SignalWindow(3);
1070                 this.simplepages = new SimplePages('contentMain');
1071                 this.timers = new Timers('contentMain');
1072                 this.volume = new Volume('volContent');
1073
1074                 this.currentData = {};
1075                 this.currentLocation = "";
1076                 this.currentTag = "";
1077                 this.deviceInfo = "";
1078
1079                 this.navlut = {
1080                         'tv': {
1081                                 'bouquets' : this.bouquets.loadBouquetsTv.bind(this.bouquets),
1082                                 'providers' : this.bouquets.loadProviderTv.bind(this.bouquets),
1083                                 'all' : this.services.loadAllTv.bind(this.services)
1084                                 },
1085                         'radio': {
1086                                 'bouquets' : this.bouquets.loadBouquetsRadio.bind(this.bouquets),
1087                                 'providers' : this.bouquets.loadProviderRadio.bind(this.bouquets),
1088                                 'all' : this.services.loadAllRadio.bind(this.services)
1089                         },
1090                         'movies':{
1091                                 'list' : function(){}
1092                         },
1093                         'timer': {
1094                                 'create' : this.timers.create.bind(this.timers),
1095                                 'edit' : false,
1096                                 'list' : function() { this.loadContentDynamic(this.timers.loadList.bind(this.timers), strings.timers); }.bind(this)
1097                         },
1098                         'control': {
1099                                 'message' : this.simplepages.loadMessage.bind(this.simplepages),
1100                                 'power' : this.simplepages.loadPower.bind(this.simplepages),
1101                                 'osdshot' : this.screenshots.shootOsd.bind(this.screenshots),
1102                                 'screenshot' : this.screenshots.shootAll.bind(this.screenshots),
1103                                 'videoshot' : this.screenshots.shootVideo.bind(this.screenshots)
1104                         },
1105                         'extras': {
1106                                 'about' : this.simplepages.loadAbout.bind(this.simplepages),
1107                                 'deviceinfo' : this.simplepages.loadDeviceInfo.bind(this.simplepages),
1108                                 'mediaplayer' : function() { this.loadContentDynamic(this.mediaplayer.load.bind(this.mediaplayer), strings.mediaplayer); }.bind(this),
1109                                 'settings' : this.simplepages.loadSettings.bind(this.simplepages),
1110                                 'tools' : this.simplepages.loadTools.bind(this.simplepages)
1111                         }
1112                 };
1113                 if(userprefs.data.style != "dark" && userprefs.data.style != "light"){
1114                         userprefs.data.style = "dark";
1115                         userprefs.save();
1116                 }
1117                 //this.styleChanged();
1118         },
1119
1120         hideNotifier: function(){
1121                 debug("[E2WebCore].hideNotifier");
1122                 $('notification').fadeOut(500);
1123         },
1124
1125         notify: function(text, state){
1126                 debug("[E2WebCore].notify");
1127                 notif = $('notification');
1128                 if(notif !== null){
1129                         //clear possibly existing hideNotifier timeout of a previous notfication
1130                         clearTimeout(this.hideNotifierTimeout);
1131                         if(state === false){
1132                                 notif.style.background = "#C00";
1133                         } else {
1134                                 notif.style.background = "#85C247";
1135                         }
1136                         this.set('notification', "<div>"+text+"</div>");
1137                         notif.fadeIn({'delay' : 500, 'to' : 90});
1138                         var _this = this;
1139                         this.hideNotifierTimeout = setTimeout(_this.hideNotifier.bind(this), 5000);
1140                 }
1141         },
1142
1143         set: function(element, value){
1144                 element = parent.$(element);
1145                 if (element){
1146                         element.update(value);
1147                 }
1148         },
1149
1150         setAjaxLoad: function(targetElement){
1151                 target = $(targetElement);
1152                 if(target != null){
1153                         target.update( getAjaxLoad() );
1154                 }
1155         },
1156
1157         messageBox: function(message){
1158                 alert(message);
1159         },
1160
1161         popUpBlockerHint: function(){
1162                 if(!this.popUpBlockerHinted){
1163                         this.popUpBlockerHinted = true;
1164                         this.messageBox("Please disable your Popup-Blocker for enigma2 WebControl to work flawlessly!");
1165
1166                 }
1167         },
1168
1169         setWindowContent: function(window, html){
1170                 window.document.write(html);
1171                 window.document.close();
1172         },
1173
1174         popup: function(title, html, width, height, x, y){
1175                 try {
1176                         var popup = window.open('about:blank',title,'scrollbars=yes, width='+width+',height='+height+',resizable=yes');
1177                         this.setWindowContent(popup, html);
1178                         return popup;
1179                 } catch(e){
1180                         this.popUpBlockerHint();
1181                         return "";
1182                 }
1183         },
1184
1185         delayedUpdateItems: function(){
1186                 var _this = this;
1187                 setTimeout(_this.updateItems.bind(this), 2000);
1188         },
1189
1190         updateItems: function(){
1191                 debug("[E2WebCore].updateItems");
1192                 this.current.load();
1193                 this.power.inStandby(this.onPowerStateAvailable.bind(this));
1194         },
1195
1196         onPowerStateAvailable: function(isStandby){
1197                 if(isStandby){
1198                         $('openSignalPanelImg').src="/web-data/img/transmit_grey.png";
1199                 } else {
1200                         $('openSignalPanelImg').src="/web-data/img/transmit_blue.png";
1201                 }
1202         },
1203
1204         updateItemsLazy: function(){
1205                 debug("[E2WebCore].updateItemsLazy");
1206                 this.services.getNowNext();
1207                 this.services.getSubservices();
1208         },
1209
1210         startUpdateCurrentPoller: function(){
1211                 debug("[E2WebCore].startUpdateCurrentPoller");
1212                 clearInterval(this.updateCurrentPoller);
1213                 var _this = this;
1214                 this.updateCurrentPoller = setInterval(_this.updateItems.bind(this), userprefs.data.updateCurrentInterval);
1215         },
1216
1217         stopUpdateCurrentPoller: function(){
1218                 clearInterval(this.updateCurrentPoller);
1219         },
1220
1221         startUpdateBouquetItemsPoller: function(){
1222                 debug("[E2WebCore].startUpdateBouquetItemsPoller");
1223                 clearInterval(this.updateBouquetItemsPoller);
1224                 var _this = this;
1225                 this.updateBouquetItemsPoller = setInterval(_this.updateItemsLazy.bind(this), userprefs.data.updateBouquetInterval);
1226         },
1227
1228         stopUpdateBouquetItemsPoller: function(){
1229                 debug("[E2WebCore].stopUpdateBouquetItemsPoller");
1230                 clearInterval(this.updateBouquetItemsPoller);
1231         },
1232
1233         setNavHighlight: function(){
1234                 var navitems = $$(".navmenu");
1235                 navitems.each(function(element){
1236                         var mode = element.readAttribute("data-mode");
1237                         var navselected = "navselected";
1238                         if(mode == this.mode){
1239                                 element.addClassName(navselected);
1240                         } else {
1241                                 element.removeClassName(navselected);
1242                         }
1243                 }.bind(this));
1244         },
1245
1246         onHashChanged: function(isReload){
1247                 var hash = hashListener.getHash();
1248                 var parts = hash.split("/");
1249
1250                 var len = parts.length;
1251                 if(len >= 2){
1252                         var mode = parts[1];
1253                         if(mode != this.mode || isReload || ( len <= 2 && this.subMode != '') ){
1254                                 this.switchMode(mode, len == 2);
1255                                 this.subMode = '';
1256                         }
1257                         this.mode = mode;
1258
1259                         this.setNavHighlight();
1260
1261                         if(len > 2){
1262                                 var subMode = parts[2];
1263                                 if(subMode != this.subMode || isReload){
1264                                         this.subMode = subMode;
1265                                         if(!this.navlut[this.mode][this.subMode]){
1266                                                 return;
1267                                         } else {
1268                                                 if(this.mode != "movies")
1269                                                         this.navlut[this.mode][this.subMode]();
1270                                         }
1271                                 }
1272                                 if(len > 3){
1273                                         switch(this.mode){
1274                                         case 'tv':
1275                                         case 'radio':
1276                                                 this.services.load(unescape(parts[3]));
1277                                                 break;
1278                                         case 'movies':
1279                                                 var location = decodeURIComponent(parts[4]);
1280                                                 var tag = decodeURIComponent(parts[5]);
1281
1282                                                 this.currentLocation = location;
1283                                                 this.currentTag = tag;
1284                                                 this.loadContentDynamic(
1285                                                         function(){
1286                                                                 this.movies.load(location, tag);
1287                                                         }.bind(this),
1288                                                         strings.movies,
1289                                                         true
1290                                                 );
1291
1292                                                 break;
1293                                         case 'extras':
1294                                                 if(subMode == 'mediaplayer'){
1295                                                         this.mediaplayer.load(decodeURIComponent(parts[3]));
1296                                                 }
1297                                                 break;
1298                                         default:
1299                                                 return;
1300                                         }
1301                                 }
1302                         }
1303                 }
1304         },
1305
1306         getBaseHash: function(){
1307                 var hash = ['#!', this.mode].join("/");
1308                 if(this.subMode != ''){
1309                         hash = [hash, this.subMode].join("/");
1310                 }
1311                 return hash;
1312         },
1313
1314         loadDefault: function(){
1315                 debug("[E2WebCore].loadDefault");
1316                 this.switchMode('tv');
1317                 this.mode = 'tv';
1318                 this.subMode = 'bouquets';
1319                 this.bouquets.load(bouquetsTv, true);
1320         },
1321
1322         run: function(){
1323                 debug("[E2WebCore].run");
1324                 this.sessionProvider.load({});
1325         },
1326
1327         onSessionAvailable: function(sid){
1328                 debug("[E2WebCore].onSessionAvailable, " + sid)
1329                 global_sessionid = sid;
1330
1331                 this.currentLocation = this.lt.getCurrentLocation(function(location){this.currentLocation = location;}.bind(this));
1332                 this.deviceInfo = this.simplepages.getDeviceInfo(function(info){this.deviceInfo = info;}.bind(this));
1333                 
1334                 if( parseNr(userprefs.data.updateCurrentInterval) < 10000){
1335                         userprefs.data.updateCurrentInterval = 120000;
1336                         userprefs.save();
1337                 }
1338
1339                 if( parseNr(userprefs.data.updateBouquetInterval) < 60000 ){
1340                         userprefs.data.updateBouquetInterval = 300000;
1341                         userprefs.save();
1342                 }
1343
1344                 if (typeof document.body.style.maxHeight == undefined) {
1345                         alert("Due to the tremendous amount of work needed to get everthing to " +
1346                         "work properly, there is (for now) no support for Internet Explorer Versions below 7");
1347                 }
1348                 hashListener.onHashChanged = this.onHashChanged.bind(this);
1349                 hashListener.init();
1350
1351                 this.registerEvents();
1352
1353                 this.setAjaxLoad('navContent');
1354                 this.setAjaxLoad('contentMain');
1355                 RequestCounter.addChangedCallback(this.onAjaxRequestCountChanged.bind(this));
1356
1357                 templateEngine.fetch('tplServiceListEPGItem');
1358                 templateEngine.fetch('tplBouquetsAndServices');
1359                 templateEngine.fetch('tplCurrent');
1360                 if(!hashListener.getHash().length >= 1){
1361                         this.loadDefault();
1362                 }
1363                 this.updateItems();
1364                 this.startUpdateCurrentPoller();
1365         },
1366
1367         onSessionFailed: function(transport){
1368                 this.notify("FATAL ERROR! NO SESSION!", true)
1369         },
1370
1371         onAjaxRequestCountChanged: function(count){
1372                 debug("Active Request count: " + RequestCounter.count);
1373                 if(count > 0)
1374                         $('ajaxLoad').show();
1375                 else
1376                         $('ajaxLoad').hide();
1377         },
1378
1379         registerEvents: function(){
1380                 debug("[E2WebCore].registerEvents");
1381                 //Hash-Reload-Fix
1382                 //HACK :: THIS IS EVIL VOODOO, DON'T TRY THIS AT HOME!
1383                 document.on(
1384                         'click',
1385                         'a',
1386                         function(event, element){
1387                                 var parts = element.href.split('#');
1388                                 var curHost = window.location.href.split('#')[0];
1389                                 //Don't do this crazy stuff when the target is another host!
1390                                 if(curHost == parts[0]){
1391                                         if (parts.length > 1){
1392                                                 if(parts[1] != ''){
1393                                                         if(window.location == element.href){
1394                                                                 this.onHashChanged(true);
1395                                                                 return;
1396                                                         }else{
1397                                                                 window.location == element.href;
1398                                                                 return;
1399                                                         }
1400                                                 } else {
1401                                                         element.href = window.location;
1402                                                 }
1403                                                 return false;
1404                                         }
1405                                 }
1406                         }.bind(this)
1407                 );
1408                 //Header
1409                 $('openSignalPanel').on(
1410                         'click',
1411                         function(event, element){
1412                                 this.signal.load();
1413                                 event.stop();
1414                         }.bind(this)
1415                 );
1416                 $('instantRecord').on(
1417                         'click',
1418                         function(event, element){
1419                                 var menu = $('instantRecordMenu');
1420                                 if(menu.visible()){
1421                                         menu.hide();
1422                                 } else {
1423                                         menu.show();
1424                                 }
1425                                 event.stop();
1426                         }
1427                 );
1428                 document.on(
1429                         'click',
1430                         '.doInstantRecord',
1431                         function(event, element){
1432                                 var menu = $('instantRecordMenu');
1433                                 this.timers.recordNow(
1434                                         element.readAttribute('data-type'),
1435                                         function(result){
1436                                                 menu.hide();
1437                                         }
1438                                 );
1439                         }.bind(this)
1440                 );
1441                 //Current
1442                 $('current').on(
1443                         'click',
1444                         '.currentExtShowHide',
1445                         function(event, element){
1446                                 this.current.toggleVisibility(element);
1447                                 event.stop();
1448                         }.bind(this)
1449                 );
1450                 $('current').on(
1451                                 'click',
1452                                 '.currentEpg',
1453                                 function(event, element){
1454                                         var ref = unescape( element.readAttribute('data-servicereference') );
1455                                         this.epg.load(ref);
1456                                         event.stop();
1457                                 }.bind(this)
1458                         );
1459                 //EPG-Search
1460                 $('epgSearchForm').on(
1461                         'submit',
1462                         function(event, element){
1463                                 this.epg.search($F('epgSearch'));
1464                                 event.stop();
1465                         }.bind(this)
1466                 );
1467                 $('epgSearch').on(
1468                         'focus',
1469                         function(event, element){
1470                                 element.value = "";
1471                         }.bind(this)
1472                 );
1473                 $('epgSearchClear').on(
1474                                 'click',
1475                                 function(event, element){
1476                                         $('epgSearch').value = '';
1477                                         return false;
1478                                 }.bind(this)
1479                 );
1480                 //Movienav
1481                 var changeevt = Prototype.Browser.IE ? "click" : "change";
1482                 var nav = $('navContent');
1483                 nav.on(
1484                         changeevt,
1485                         '.mNavLocTag',
1486                         function(event, element){
1487                                 var l = $('locations');
1488                                 var t = $('tags');
1489                                 var location = l.options[l.selectedIndex].value;
1490                                 var tag = t.options[t.selectedIndex].value;
1491                                 var hash = [this.getBaseHash(), "filter", encodeURIComponent(location), encodeURIComponent(tag)].join("/");
1492                                 if(hash != '#'+hashListener.getHash() || !Prototype.Browser.IE)
1493                                         hashListener.setHash(hash);
1494                         }.bind(this)
1495                 );
1496                 $('contentHdExt').on(
1497                         changeevt,
1498                         '.mNavLocTag',
1499                         function(event, element){
1500                                 var l = $('locations');
1501                                 var t = $('tags');
1502                                 var location = l.options[l.selectedIndex].value;
1503                                 var tag = t.options[t.selectedIndex].value;
1504                                 var hash = [this.getBaseHash(), "filter", encodeURIComponent(location), encodeURIComponent(tag)].join("/");
1505                                 if(hash != '#'+hashListener.getHash() || !Prototype.Browser.IE)
1506                                         hashListener.setHash(hash);
1507                         }.bind(this)
1508                 );
1509                 //RemoteControl
1510                 nav.on(
1511                         'click',
1512                         '.webremote',
1513                         this.remote.open.bind(this.remote)
1514                 );
1515                 //Volume
1516                 $('navVolume').on(
1517                         'click',
1518                         'a.volume',
1519                         function(event, element){
1520                                 this.volume.set(element.readAttribute('data-volume'));
1521                                 return false;
1522                         }.bind(this)
1523                 );
1524
1525                 //Content
1526                 var content = $('contentMain');
1527                 //MediaPlayer
1528                 content.on(
1529                         'click',
1530                         '.mpCmd',
1531                         function(event, element){
1532                                 this.mediaplayer.command(element.readAttribute('data-command'));
1533                         }.bind(this)
1534                 );
1535                 content.on(
1536                         'click',
1537                         '.mpPlayFile',
1538                         function(event, element){
1539                                 var parent = element.up('.mpListItem');
1540                                 var ref = decodeURIComponent( parent.readAttribute('data-servicereference') );
1541                                 this.mediaplayer.playFile(ref);
1542                                 event.stop();
1543                         }.bind(this)
1544                 );
1545                 content.on(
1546                                 'click',
1547                                 '.mpAddFile',
1548                                 function(event, element){
1549                                         var parent = element.up('.mpListItem');
1550                                         var ref = decodeURIComponent( parent.readAttribute('data-servicereference') );
1551                                         this.mediaplayer.addFile(ref);
1552                                         event.stop();
1553                                 }.bind(this)
1554                         );
1555                 content.on(
1556                         'click',
1557                         '.mpRemoveFile',
1558                         function(event, element){
1559                                 var parent = element.up('.mpListItem');
1560                                 var ref = decodeURIComponent( parent.readAttribute('data-servicereference') );
1561                                 this.mediaplayer.removeFile(ref);
1562                                 event.stop();
1563                         }.bind(this)
1564                 );
1565                 content.on(
1566                                 'click',
1567                                 '.mpSavePlaylist',
1568                                 function(event, element){
1569                                         var filename = prompt('Please enter a filename for the playlist', 'playlist');
1570                                         if(filename != null && filename != ""){
1571                                                 this.mediaplayer.savePlaylist(filename);
1572                                         }
1573                                 }.bind(this)
1574                         );
1575                 //Message
1576                 content.on(
1577                         'click',
1578                         '.messageSend',
1579                         function(event, element){
1580                                 var t = $('messageType');
1581                                 text = $('messageText').value;
1582                                 timeout = $('messageTimeout').value;
1583                                 type = t.options[t.selectedIndex].value;
1584                                 this.messages.send(text, type, timeout);
1585                         }.bind(this)
1586                 );
1587                 //Movielist
1588                 content.on(
1589                         'click',
1590                         'a.mListDelete',
1591                         function(event, element){
1592                                 this.movies.del(element);
1593                                 event.stop();
1594                         }.bind(this)
1595                 );
1596                 //Powerstate
1597                 content.on(
1598                         'click',
1599                         '.powerState',
1600                         function(event, element){
1601                                 var newState = element.readAttribute("data-state");
1602                                 var cb = function(isStandby){
1603                                         var text = "Device is now Running";
1604                                         switch(this.power.STATES[newState]){
1605                                         case this.power.STATES.toggle:
1606                                                 if(isStandby)
1607                                                         text = "Device is now in Soft-Standby";
1608                                                 break;
1609                                         case this.power.STATES.deep:
1610                                                 if(isStandby)
1611                                                         text = "Device will go into deep standby (if possible, check OSD for messages)";
1612                                                 else
1613                                                         text = "Cannot shutdown!";
1614                                                 break;
1615                                         case this.power.STATES.reboot:
1616                                                 if(isStandby)
1617                                                         text = "Device will reboot now (if possible, check OSD for messages)";
1618                                                 else
1619                                                         text = "Cannot reboot!";
1620                                                 break;
1621                                         case this.power.STATES.gui:
1622                                                 if(isStandby)
1623                                                         text = "GUI will restart now (if possible, check OSD for messages)";
1624                                                 else
1625                                                         text = "Cannot restart GUI!";
1626                                                 break;
1627                                         }
1628                                         this.notify(text, true);
1629                                         this.onPowerStateAvailable(isStandby);
1630                                 }.bind(this);
1631                                 this.power.set(newState, cb);
1632                         }.bind(this)
1633                 );
1634                 //Settings
1635                 content.on(
1636                         'click',
1637                         '.saveSettings',
1638                         function(event, element){
1639                                 this.saveSettings();
1640                         }.bind(this)
1641                 );
1642                 //Bouquets
1643                 content.on(
1644                         'click',
1645                         'a.bListSLink',
1646                         function(event, element){
1647                                 setContentHd(element.readAttribute("data-servicename"));
1648                         }
1649                 );
1650                 content.on(
1651                         'click',
1652                         'a.bListEpg',
1653                         function(event, element){
1654                                 var sref = decodeURIComponent( element.readAttribute("data-servicereference") );
1655                                 this.multiepg.load(sref);
1656                                 event.stop();
1657                         }.bind(this)
1658                 );
1659
1660                 //Servicelist
1661                 content.on(
1662                         'click',
1663                         'a.sListSLink',
1664                         function(event, element){
1665                                 var ref = decodeURIComponent( element.id );
1666                                 this.services.zap(ref, this.delayedUpdateItems.bind(this));
1667                                 event.stop();
1668                         }.bind(this)
1669                 );
1670                 content.on(
1671                         'click',
1672                         'a.sListServiceEpg',
1673                         function(event, element){
1674                                 var ref = unescape( element.readAttribute('data-servicereference') );
1675                                 this.epg.load(ref);
1676                                 event.stop();
1677                         }.bind(this)
1678                 );
1679                 content.on(
1680                         'click',
1681                         'a.sListExtEpg',
1682                         function(event, element){
1683                                 var target = element.up('.sListEPGItem').down('.sListExtEpgLong');
1684
1685                                 if(target){
1686                                         var bullet = element.down('.sListBulletToggle');
1687                                         if(target.visible()){
1688                                                 target.hide();
1689                                                 bullet.src = "/web-data/img/toggle_expand_small.png";
1690                                                 bullet.alt = "+";
1691                                         } else {
1692                                                 target.show();
1693                                                 bullet.src = "/web-data/img/toggle_collapse_small.png";
1694                                                 bullet.alt = "-";
1695                                         }
1696                                 }
1697                                 event.stop();
1698                         }.bind(this)
1699                 );
1700                 content.on(
1701                         'click',
1702                         '.sListAddTimer',
1703                         function(event, element){
1704                                 core.timers.addByEventId(element, 0);
1705                                 event.stop();
1706                         }
1707                 );
1708                 content.on(
1709                         'click',
1710                         '.sListZapTimer',
1711                         function(event, element){
1712                                 core.timers.addByEventId(element, 1);
1713                                 event.stop();
1714                         }
1715                 );
1716                 content.on(
1717                         'click',
1718                         '.sListEditTimer',
1719                         function(event, element){
1720                                 var hash = ["#!/timer", "edit"].join("/");
1721                                 hashListener.setHash(hash);
1722                                 core.timers.editFromEvent(element);
1723                                 event.stop();
1724                         }
1725                 );
1726
1727                 //Timerlist
1728                 content.on(
1729                         'click',
1730                         '.tListDelete',
1731                         function(event, element){
1732                                 this.timers.del(element);
1733                                 event.stop();
1734                         }.bind(this)
1735                 );
1736                 content.on(
1737                         'click',
1738                         '.tListToggleDisabled',
1739                         function(event, element){
1740                                 this.timers.toggleDisabled(element);
1741                                 event.stop();
1742                         }.bind(this)
1743                 );
1744                 content.on(
1745                         'click',
1746                         '.tListEdit',
1747                         function(event, element){
1748                                 var hash = ["#!/timer", "edit"].join("/");
1749                                 hashListener.setHash(hash);
1750                                 this.timers.edit(element);
1751                                 return false;
1752                         }.bind(this)
1753                 );
1754                 content.on(
1755                         'click',
1756                         '.tListCleanup',
1757                         function(event, element){
1758                                 this.timers.cleanupList();
1759                                 return false;
1760                         }.bind(this)
1761                 );
1762                 //Timer Editing
1763                 content.on(
1764                         'change',
1765                         '.tEditRepeated',
1766                         function(event, element){
1767                                 var days = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su'];
1768                                 var weekdays = days.slice(0,5);
1769
1770                                 switch(element.id){
1771                                 case 'mf':
1772                                         var checked = element.checked;
1773                                         weekdays.each(function(day){
1774                                                 $(day).checked = checked;
1775                                         });
1776                                         if(checked){
1777                                                 var others = ['sa', 'su', 'ms'];
1778                                                 others.each(function(item){
1779                                                         $(item).checked = false;
1780                                                 });
1781                                         }
1782                                         break;
1783                                 case 'ms':
1784                                         var checked = element.checked;
1785                                         days.each(function(day){
1786                                                 $(day).checked = checked;
1787                                         });
1788                                         if(checked){
1789                                                 $('mf').checked = false;
1790                                         }
1791                                         break;
1792                                 default:
1793                                         var weekdays = true;
1794                                         var alldays = true;
1795                                         days.each(function(day){
1796                                                 day = $(day);
1797                                                 if(day.value <= 64){
1798                                                         if(!day.checked){
1799                                                                 alldays = false;
1800                                                                 if(day.value <= 16){
1801                                                                         weekdays = false;
1802                                                                         return
1803                                                                 }
1804                                                         } else {
1805                                                                 if(day.value > 16){
1806                                                                         weekdays = false;
1807                                                                 }
1808                                                         }
1809                                                 }
1810                                         });
1811                                         if(alldays){
1812                                                 $('mf').checked = false;
1813                                                 $('ms').checked = true;
1814                                         } else if (weekdays) {
1815                                                 $('mf').checked = true;
1816                                                 $('ms').checked = false;
1817                                         } else {
1818                                                 $('mf').checked = false;
1819                                                 $('ms').checked = false;
1820                                         }
1821                                 }
1822                         }
1823                 );
1824                 content.on(
1825                         'change',
1826                         '.tEditBouquet',
1827                         function(event, element){
1828                                 var value = unescape( element.options[element.selectedIndex].value );
1829                                 core.timers.onBouquetChanged(value);
1830                         }.bind(this)
1831                 );
1832                 content.on(
1833                         'click',
1834                         '.tEditTag',
1835                         function(event, element){
1836                                 var selected = 'selected';
1837                                 var attr = 'data-selected';
1838                                 if(element.hasClassName(selected)){
1839                                         element.removeClassName(selected);
1840                                         element.writeAttribute(attr, '');
1841                                 } else {
1842                                         element.addClassName(selected);
1843                                         element.writeAttribute(attr, selected);
1844                                 }
1845                                 event.stop();
1846                         }.bind(this)
1847                 );
1848                 content.on(
1849                         'click',
1850                         '.tEditSave',
1851                         function(event, element){
1852                                 this.timers.save($('timerEditForm'));
1853                         }.bind(this)
1854                 );
1855
1856                 $('webTv').on(
1857                         'click',
1858                         function(event, element){
1859                                 window.open('/web-data/tpl/default/streaminterface/index.html', 'WebTV', 'scrollbars=no, width=800, height=740');
1860                                 event.stop();
1861                         }.bind(this)
1862                 );
1863         },
1864
1865         /*
1866          * Loads another navigation template and sets the navigation header
1867          * @param template - The name of the template
1868          * @param title - The title to set for the navigation
1869          */
1870         reloadNav: function(template, title, callback){
1871                 this.setAjaxLoad('navContent');
1872                 templateEngine.process(template, null, 'navContent', callback);
1873                 setNavHd(title);
1874         },
1875
1876         reloadNavDynamic: function(fnc, title){
1877                 this.setAjaxLoad('navContent');
1878                 setNavHd(title);
1879                 fnc();
1880         },
1881
1882         /*
1883          * Loads dynamic content to $(contentMain) by calling a execution function
1884          * @param fnc - The function used to load the content
1885          * @param title - The Title to set on the contentpanel
1886          */
1887         loadContentDynamic: function(fnc, title, keepHdExt){
1888                 setContentHd(title, keepHdExt);
1889                 this.stopUpdateBouquetItemsPoller();
1890                 fnc();
1891         },
1892
1893         /*
1894          * Loads a static template to $(contentMain)
1895          * @param template - Name of the Template
1896          * @param title - The Title to set on the Content-Panel
1897          */
1898         loadContentStatic: function(template, title){
1899                 this.setAjaxLoad('contentMain');
1900                 setContentHd(title);
1901                 this.stopUpdateBouquetItemsPoller();
1902                 templateEngine.process(template, null, 'contentMain');
1903         },
1904
1905         setEmptyContent: function(id, text){
1906                 $(id).update('<div class="block center fullwidth oneliner">' + text + '</div>');
1907         },
1908
1909         switchMode: function(mode, initContent){
1910                 if(initContent){
1911                         this.setEmptyContent('contentMain', strings.select_submenu);
1912                         setContentHd('...');
1913                 }
1914
1915                 switch(mode){
1916                 case "tv":
1917                         if(this.mode != 'tv' && this.mode != 'radio'){
1918                                 this.services.registerEvents();
1919                         }
1920                         this.reloadNav('tplNavTv', strings.television);
1921                         break;
1922
1923                 case "radio":
1924                         if(this.mode != 'tv' && this.mode != 'radio'){
1925                                 this.services.registerEvents();
1926                         }
1927                         this.reloadNav('tplNavRadio', strings.radio);
1928                         break;
1929
1930                 case "movies":
1931                         this.reloadNavDynamic(this.movies.loadNav.bind(this.movies), strings.movies);
1932                         break;
1933
1934                 case "timer":
1935                         this.reloadNav('tplNavTimer', strings.timers);
1936                         break;
1937
1938                 case "control":
1939                         this.reloadNav('tplNavBoxControl', strings.boxcontrol);
1940                         break;
1941
1942                 case "extras":
1943                         this.reloadNav('tplNavExtras', strings.extras, this.externals.load.bind(this.externals));
1944                         break;
1945
1946                 default:
1947                         break;
1948                 }
1949         },
1950         
1951         styleChanged: function(){
1952                 if(userprefs.data.style == 'light'){
1953                         $('style_light').disabled = false;
1954                         $('style_dark').disabled = true;
1955                 } else {
1956                         $('style_dark').disabled = false;
1957                         $('style_light').disabled = true;
1958                 }
1959         },
1960
1961         saveSettings: function(){
1962                 userprefs.load();
1963                 var changed = false;
1964
1965                 var l = $('interfaceStyle');
1966                 var style = l.options[l.selectedIndex].value;
1967                 if(style != userprefs.data.style){
1968                         userprefs.data.style = style;
1969                         changed = true;
1970                         this.styleChanged();
1971                 }
1972                 
1973                 var debug = $('enableDebug').checked;
1974                 if(debug != undefined){
1975                         if( userprefs.data.debug != debug ){
1976                                 userprefs.data.debug = debug;
1977                                 changed = true;
1978                         }
1979                 }
1980
1981                 var updateCurrentInterval = parseNr( $F('updateCurrentInterval') ) * 1000;
1982                 if( updateCurrentInterval < 10000){
1983                         updateCurrentInterval = 120000;
1984                 }
1985
1986                 if( userprefs.data.updateCurrentInterval != updateCurrentInterval){
1987                         userprefs.data.updateCurrentInterval = updateCurrentInterval;
1988
1989                         changed = true;
1990                         this.startUpdateCurrentPoller();
1991                 }
1992
1993                 var updateBouquetInterval = parseNr( $F('updateBouquetInterval') ) * 1000;
1994                 if( updateBouquetInterval < 60000){
1995                         updateBouquetInterval = 300000;
1996                 }
1997
1998                 if( userprefs.data.updateBouquetInterval != updateBouquetInterval){
1999                         userprefs.data.updateBouquetInterval = updateBouquetInterval;
2000
2001                         changed = true;
2002                         this.startUpdateBouquetItemsPoller();
2003                 }
2004
2005                 if(changed){
2006                         userprefs.save();
2007                         this.notify("Settings saved");
2008                 } else {
2009                         this.notify("Nothing changed! No need to save!");
2010                 }
2011         }
2012 });
2013 core = new E2WebCore();