show new remote control for dm7080hd
[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         onInstantPlay: function(event, element){
504                 var ref = $F('instantPlay').gsub(":", "%3a");
505                 ref = "4097:0:1:0:0:0:0:0:0:0:" + ref;
506                 this.playFile(ref);
507                 event.stop();
508         },
509
510         addInstantPlayInput: function(){
511                 var form = new Element('form');
512                 form.id = 'instantPlayForm';
513                 var input = new Element('input');
514                 input.id = 'instantPlay';
515                 setInputPlaceholder(input, strings.play);
516
517                 form.insert({top : input});
518                 form.on('submit', this.onInstantPlay.bind(this));
519
520                 $('contentHdExt').update(form);
521         },
522
523         onFinished: function(){
524                 this.addInstantPlayInput();
525         }
526 });
527
528 var Messages = Class.create({
529         initialize: function(){
530                 this.handler = new SimpleRequestHandler();
531         },
532
533         send: function(text, type, timeout){
534                 this.handler.load(URL.message, {'text' : text, 'type' : type, 'timeout' : timeout});
535         }
536 });
537
538 var Movies = Class.create(Controller, {
539         initialize: function($super, listTarget, navTarget, locTarget){
540                 $super(new MovieListHandler(listTarget));
541                 this.navHandler = new MovieNavHandler(navTarget, locTarget);
542         },
543
544         load: function(location, tags){
545                 if(!location){
546                         var sethash = function(location){
547                                 var hash = [core.getBaseHash(), "filter", encodeURIComponent(location), encodeURIComponent(tags)].join("/");
548                                 hashListener.setHash(hash);
549                         };
550                         if(core.currentLocation == ""){ //wait for currentLocation to be set;
551                                 core.lt.getCurrentLocation(sethash);
552                         } else {
553                                 sethash(core.currentLocation);
554                         }
555                         return;
556                 }
557
558                 this.handler.load({'dirname' : location, 'tag' : tags});
559         },
560
561         loadNav: function(){
562                 core.lt.getLocationsAndTags(this.showNav.bind(this));
563         },
564
565         showNav: function(currentLocation, locations, tags){
566                 this.navHandler.load(toOptionList(locations, currentLocation), toOptionList(tags, core.currentTag));
567         },
568
569         del: function(element){
570                 this.handler.del(element);
571         }
572 });
573
574 var RemoteControl = Class.create({
575         initialize: function(){
576                 this.handler = new RemoteControlHandler();
577                 var _this = this;
578                 this.handler.onFinished.push(_this.onKeySent.bind(_this));
579                 this.shotType = '';
580                 this.window = '';
581         },
582
583         open: function(){
584                 if(!this.window)
585                         this.window = '';
586                 if (this.window.closed || !this.window.location){
587                         var tpl;
588                         switch(core.deviceInfo.info.devicename){
589                         case 'dm8000':
590                         case 'dm7020hd':
591                         case 'dm800sev2':
592                         case 'dm500hdv2':
593                         case 'dm7080':
594                                 tpl = 'tplWebRemote';
595                                 break;
596                         default:
597                                 tpl = 'tplWebRemoteOld';
598                         }
599
600                         templateEngine.process(tpl, null, function(html){
601                                 this.eventsregistered = false;
602                                 this.window = core.popup('WebRemote', html, 250, 650);
603                                 this.registerEvents();
604                         }.bind(this));
605                 }
606         },
607
608         sendKey: function(cmd, type, shotType){
609                 debug("[RemoteControl].sendKey: " + cmd);
610                 this.shotType = shotType;
611                 this.handler.sendKey({'command' : cmd, 'type': type});
612
613         },
614
615         onKeySent: function(){
616                 this.screenShot(this.shotType);
617         },
618
619         screenShot: function(shotType){
620                 var hash = '!/control'; //FIXME
621                 switch(shotType){
622                 case 'osd':
623                         hash = [hash, 'osdshot'].join("/");
624                         break;
625                 case 'all':
626                         hash = [hash, 'screenshot'].join("/");
627                         break;
628                 default:
629                         return;
630                 }
631                 //the box needs at least a little bit of time to actually draw the window
632                 //wait 250ms before fetching a new screenshot
633                 setTimeout(
634                         function(){
635                                 var forceReload = hash == hashListener.getHash();
636                                 hashListener.setHash(hash);
637                                 if(forceReload){
638                                         core.onHashChanged(true);
639                                 }
640                         },
641                         250);
642         },
643
644         registerEvents: function(){
645                 var _this = this;
646                 var win = this.window;
647                 var elem = win.document;
648
649                 var onload = function(event){
650                         elem.on(
651                                 'click',
652                                 '.remoteKey',
653                                 function(event, element){
654                                         var id = element.readAttribute('data-keyid');
655                                         var long = _this.window.document.getElementById('long').checked;
656                                         var screenshot = _this.window.document.getElementById('screenshot').checked;
657                                         var video = _this.window.document.getElementById('video').checked;
658                                         var type = '';
659                                         if(long){
660                                                 type = 'long';
661                                         }
662                                         var shotType = '';
663                                         if(screenshot && video){
664                                                 shotType = 'all';
665                                         } else if (screenshot && !video) {
666                                                 shotType = 'osd';
667                                         }
668                                         _this.sendKey(id, type, shotType);
669                                 }
670                         );
671                         elem.on(
672                                 'click',
673                                 '.screenshot',
674                                 function(event, element){
675                                         var video = _this.window.document.getElementById('video').checked;
676                                         var shotType = 'osd';
677                                         if(video)
678                                                 shotType = 'all';
679                                         _this.screenShot(shotType);
680                                 }
681                         );
682                 };
683                 if(elem.on){
684                         onload();
685                 } else {
686                         win.onload = onload;
687                 }
688         }
689 });
690
691 var Screenshots = Class.create(Controller, {
692         TYPE_OSD : 'o',
693         TYPE_VIDEO : 'v',
694         TYPE_ALL : '',
695
696         initialize: function($super, target){
697                 $super(new ScreenshotHandler(target));
698         },
699
700         load: function(type){
701                 var filename = '/tmp/' + new Date().getTime();
702                 var params = {'format' : 'jpg', 'r': '720', 'filename' : filename};
703
704                 switch(type){
705                         case this.TYPE_OSD:
706                                 params['o'] = '';
707                                 params['n'] = '';
708                                 params['format'] = 'png';
709                                 break;
710                         case this.TYPE_VIDEO:
711                                 params['v'] = '';
712                                 break;
713                         default:
714                                 break;
715                 }
716                 this.handler.load(params);
717         },
718
719         shootOsd: function(){
720                 setContentHd(strings.screenshot_osd);
721                 this.load(this.TYPE_OSD);
722         },
723
724         shootVideo: function(){
725                 setContentHd(strings.screenshot_video);
726                 this.load(this.TYPE_VIDEO);
727         },
728
729         shootAll: function(){
730                 setContentHd(strings.screenshot_all);
731                 this.load(this.TYPE_ALL);
732         }
733 });
734
735 var Services = Class.create(Controller, {
736         initialize: function($super, target, epg){
737                 $super(new ServiceListHandler(target));
738                 this.epg = epg;
739                 this.cachedServiceElements = null;
740         },
741
742         zap: function(sRef, callback){
743                 this.handler.zap({'sRef' : sRef}, callback);
744         },
745
746         load: function(sRef){
747                 this.handler.load({'bRef' : sRef});
748         },
749
750         getNowNext: function(){
751                 this.handler.getNowNext();
752         },
753
754         getSubservices: function(){
755                 this.handler.getSubservices();
756         },
757
758         loadAll: function(ref){
759                 var tpl = 'tplBouquetsAndServices';
760                 var fnc = function(){
761                         $('contentBouquets').update(strings.all);
762                         this.load(ref);
763                 }.bind(this);
764
765                 if($('contentBouquets')){
766                         fnc();
767                 } else {
768                         templateEngine.process(
769                                 tpl,
770                                 null,
771                                 'contentMain',
772                                 fnc
773                         );
774                         }
775         },
776
777         loadAllTv: function(){
778                 this.loadAll(allTv);
779                 setContentHd(strings.all + " (" + strings.tv + ")");
780         },
781
782         loadAllRadio: function(){
783                 this.loadAll(allRadio);
784                 setContentHd(strings.all + " (" + strings.radio + ")");
785         },
786
787         onFilterFocus: function(event){
788                 event.element().value = '';
789                 this.cachedServiceElements = null;
790                 this.filter(event);
791         },
792
793         filter: function(event){
794                 var needle = event.element().value.toLowerCase();
795
796                 if(this.cachedServiceElements == null){
797                         this.cachedServiceElements = $$('.sListRow');
798                 }
799                 var cls = 'even';
800                 for(var i = 0; i < this.cachedServiceElements.length; i++){
801                         var row = this.cachedServiceElements[i];
802                         var serviceName = row.readAttribute('data-servicename');
803                         if(serviceName)
804                                 serviceName = serviceName.toLowerCase();
805                         var isMarker = serviceName == null;
806                         if( (isMarker || ( serviceName.match(needle) != needle && serviceName != "")) && needle != "" ){
807                                 row.hide();
808                         } else {
809                                 row.show();
810                                 if(isMarker)
811                                         continue;
812                                 cls = cls == 'odd' ? 'even' : 'odd';
813                                 notCls = cls == 'odd' ? 'even' : 'odd';
814
815                                 var td = row.firstDescendant();
816                                 td.removeClassName(notCls);
817                                 td.addClassName(cls);
818                         }
819                 }
820         },
821
822         addFilterInput: function(){
823                 var input = new Element('input');
824                 input.id = 'serviceFilter';
825                 setInputPlaceholder(input, strings.filter_services);
826                 $('contentHdExt').update(input);
827                 input.on('focus', this.onFilterFocus.bind(this));
828                 input.on('keyup', this.filter.bind(this));
829         },
830
831         onFinished: function(){
832                 this.addFilterInput();
833                 core.startUpdateBouquetItemsPoller();
834         }
835 });
836
837 var SignalWindow = Class.create(Controller, {
838         initialize: function($super, seconds){
839                 $super(new SignalHandler(this.show.bind(this)));
840                 this.window = '';
841                 if(!isNaN(Number(seconds))){
842                         this.seconds = seconds * 1000;
843                 } else {
844                         this.seconds = 5000;
845                 }
846                 this.interval = '';
847         },
848
849         load: function(){
850                 this.handler.load({});
851         },
852
853         reload: function(){
854                 debug('[SignalWindow].reload');
855                 if (!this.window.closed && this.window.location){
856                         this.load();
857                 } else {
858                         clearInterval(this.interval);
859                 }
860         },
861
862         show: function(html){
863                 debug('[SignalWindow].show');
864                 if (this.window.closed || !this.window.location){
865                         this.window = core.popup("SignalPanel", html, 220, 120);
866                         this.window.onbeforeunload = function(){
867                                 clearInterval(this.interval);
868                         };
869
870                         var _this = this;
871                         clearInterval(_this.interval);
872                         this.interval = setInterval(_this.reload.bind(this), _this.seconds);
873                 } else if(!this.window.closed && this.window.location) {
874                         this.window.document.write(html);
875                         this.window.document.close();
876                 }
877         }
878 });
879
880 var SimplePages = Class.create({
881         PAGE_ABOUT : 'tplAbout',
882         PAGE_MESSAGE : 'tplSendMessage',
883         PAGE_POWER : 'tplPower',
884         PAGE_SETTINGS: 'tplSettings',
885         PAGE_TOOLS: 'tplTools',
886
887         initialize: function(target){
888                 this.simpleHandler = new SimplePageHandler(target);
889                 this.deviceInfoHandler = new DeviceInfoHandler(target);
890         },
891
892         show: function(tpl, data){
893                 if(!data)
894                         data = {};
895                 this.simpleHandler.show(tpl, data);
896         },
897
898         loadAbout: function(){
899                 setContentHd(strings.about);
900                 this.show(this.PAGE_ABOUT);
901         },
902
903         loadMessage: function(){
904                 setContentHd(strings.send_message);
905                 this.show(this.PAGE_MESSAGE);
906         },
907
908         loadPower: function(){
909                 setContentHd(strings.powercontrol);
910                 this.show(this.PAGE_POWER);
911         },
912
913         loadSettings: function(){
914                 setContentHd(strings.settings);
915                 var debug = userprefs.data.debug;
916                 var debugChecked = "";
917                 if(debug){
918                         debugChecked = 'checked';
919                 }
920
921                 var updateCurrentInterval = userprefs.data.updateCurrentInterval / 1000;
922                 var updateBouquetInterval = userprefs.data.updateBouquetInterval / 1000;
923                 var style = userprefs.data.style;
924                 data = {'debug' : debugChecked,
925                                 'updateCurrentInterval' : updateCurrentInterval,
926                                 'updateBouquetInterval' : updateBouquetInterval,
927                                 'style' : style
928                         };
929                 this.show(this.PAGE_SETTINGS, data);
930         },
931
932         loadTools: function(){
933                 setContentHd(strings.tools);
934                 this.show(this.PAGE_TOOLS);
935         },
936
937         loadDeviceInfo: function(){
938                 setContentHd(strings.deviceinfo);
939                 this.deviceInfoHandler.load({});
940         },
941
942         getDeviceInfo: function(callback){
943                 this.deviceInfoHandler.get({}, callback);
944         }
945 });
946
947 var Timers = Class.create({
948         initialize: function(target){
949                 this.listHandler = new TimerListHandler(target);
950                 this.timerHandler = new TimerHandler(target, this.loadList.bind(this), [this.onTimerEditLoadFinished.bind(this)]);
951         },
952
953         loadList: function(){
954                 this.listHandler.load({});
955         },
956
957         cleanupList: function(){
958                 this.listHandler.cleanup();
959         },
960
961         create: function(){
962                 this.timerHandler.load({}, false, true);
963         },
964
965         edit: function(element){
966                 this.timerHandler.load(element, true);
967         },
968
969         editFromEvent: function(element){
970                 this.timerHandler.load(element, false, false, true);
971         },
972
973         save: function(element){
974                 this.timerHandler.commitForm(element);
975         },
976
977         onBouquetChanged: function(bRef){
978                 this.timerHandler.onBouquetChanged(bRef, this.onUpdatedServiceListReady.bind(this));
979         },
980
981         onUpdatedServiceListReady: function(data, timer){
982                 var serviceSel = $('service');
983                 var options = serviceSel.options;
984                 options.length = 0;
985
986                 var i = 0;
987                 data.services.each(function(s){
988                         var selected = false;
989                         if(timer.servicereference == unescape(s.servicereference)){
990                                 selected = true;
991                         }
992                         options.add ( new Option(s.servicename, s.servicereference, false, selected) );
993                         i++;
994                 });
995         },
996
997         recordNow: function(type, callback){
998                 this.timerHandler.recordNow(type, callback);
999         },
1000
1001         addByEventId: function(element, justplay){
1002                 var parent = element.up('.epgListItem');
1003                 var sRef = unescape(parent.readAttribute('data-servicereference'));
1004                 var eventId = unescape(parent.readAttribute('data-eventid'));
1005                 this.timerHandler.addByEventId(sRef, eventId, justplay);
1006         },
1007
1008         toggleDisabled: function(element){
1009                 this.timerHandler.toggleDisabled(element);
1010         },
1011
1012         del: function(element){
1013                 this.timerHandler.del(element);
1014         },
1015
1016         onTimerEditLoadFinished: function(){
1017                 debug("[Timers].onTimerEditLoadFinished");
1018                 datePickerController.destroyDatePicker('sdate');
1019                 datePickerController.destroyDatePicker('edate');
1020                 var today = new Date();
1021                 var pad = function(value, length) {
1022                         length = length || 2;
1023                         return "0000".substr(0,length - Math.min(String(value).length, length)) + value;
1024                 };
1025                 var opts = {
1026                                 showWeeks: true,
1027                                 noFadeEffect: true,
1028                                 rangeLow: today.getFullYear() + "" + pad(today.getMonth()+1) + pad(today.getDate())
1029                         };
1030
1031
1032                 opts['formElements'] = { 'sdate' : 'Y-ds-m-ds-d'};
1033                 datePickerController.createDatePicker(opts);
1034
1035                 opts['formElements'] = { 'edate' : 'Y-ds-m-ds-d'};
1036                 datePickerController.createDatePicker(opts);
1037
1038         }
1039 });
1040
1041 var Volume = Class.create(Controller, {
1042         initialize: function($super, target){
1043                 $super(new VolumeHandler(target));
1044         },
1045
1046         load: function(){
1047                 this.handler.load({});
1048         },
1049
1050         set: function(value){
1051                 this.handler.load({'set' : value});
1052         }
1053 });
1054
1055 var BaseCore = Class.create({
1056         initialize: function(){
1057                 this.popUpBlockerHinted = false;
1058                 this.hideNotifierTimeout = '';
1059                 this.sessionProvider = new SessionProvider( this.onSessionAvailable.bind(this) );
1060                 if(userprefs.data.style != "dark" && userprefs.data.style != "light" && userprefs.data.style != "modern"){
1061                         userprefs.data.style = "modern";
1062                         userprefs.save();
1063                 }
1064         },
1065
1066         run: function(){
1067                 debug("[BaseCore].run");
1068                 this.sessionProvider.load({});
1069         },
1070
1071         onSessionAvailable: function(sid){
1072                 debug("[BaseCore].onSessionAvailable, " + sid);
1073                 global_sessionid = sid;
1074                 RequestCounter.addChangedCallback(this.onAjaxRequestCountChanged.bind(this));
1075         },
1076
1077         onSessionFailed: function(transport){
1078                 this.notify("FATAL ERROR! NO SESSION!", true);
1079         },
1080
1081         onAjaxRequestCountChanged: function(count){
1082                 debug("Active Request count: " + RequestCounter.count);
1083                 var ajaxload = $('ajaxLoad');
1084                 if(ajaxload){
1085                         if(count > 0)
1086                                 $('ajaxLoad').show();
1087                         else
1088                                 $('ajaxLoad').hide();
1089                 }
1090         },
1091
1092         hideNotifier: function(){
1093                 debug("[BaseCore].hideNotifier");
1094                 $('notification').fadeOut(500);
1095         },
1096
1097         notify: function(text, state){
1098                 debug("[BaseCore].notify");
1099                 var notif = $('notification');
1100                 if(notif !== null){
1101                         //clear possibly existing hideNotifier timeout of a previous notfication
1102                         clearTimeout(this.hideNotifierTimeout);
1103                         if(state === false){
1104                                 notif.style.background = "#C00";
1105                         } else {
1106                                 notif.style.background = "#85C247";
1107                         }
1108                         this.set('notification', "<div>"+text+"</div>");
1109                         notif.fadeIn({'delay' : 500, 'to' : 90});
1110                         var _this = this;
1111                         this.hideNotifierTimeout = setTimeout(_this.hideNotifier.bind(this), 5000);
1112                 }
1113         },
1114
1115         set: function(element, value){
1116                 element = parent.$(element);
1117                 if (element){
1118                         element.update(value);
1119                 }
1120         },
1121
1122         setAjaxLoad: function(targetElement){
1123                 var target = $(targetElement);
1124                 if(target != null){
1125                         target.update( getAjaxLoad() );
1126                 }
1127         },
1128         
1129         messageBox: function(message){
1130                 alert(message);
1131         },
1132
1133         popUpBlockerHint: function(){
1134                 if(!this.popUpBlockerHinted){
1135                         this.popUpBlockerHinted = true;
1136                         this.messageBox("Please disable your Popup-Blocker for enigma2 WebControl to work flawlessly!");
1137
1138                 }
1139         },
1140
1141         setWindowContent: function(window, html){
1142                 window.document.write(html);
1143                 window.document.close();
1144         },
1145
1146         popup: function(title, html, width, height, x, y){
1147                 try {
1148                         var popup = window.open('about:blank',title,'scrollbars=yes, width='+width+',height='+height+',resizable=yes');
1149                         this.setWindowContent(popup, html);
1150                         return popup;
1151                 } catch(e){
1152                         this.popUpBlockerHint();
1153                         return "";
1154                 }
1155         },
1156         
1157         styleChanged: function(){
1158         switch(userprefs.data.style){
1159                 case 'light':
1160                         $('style_dark').disabled = true;
1161                         $('style_light').disabled = false;
1162                         $('style_modern').disabled = true;
1163                         break;
1164                 case 'dark':
1165                         $('style_dark').disabled = false;
1166                         $('style_light').disabled = true;
1167                         $('style_modern').disabled = true;
1168                         break;
1169                 default:
1170                         $('style_dark').disabled = true;
1171                         $('style_light').disabled = true;
1172                         $('style_modern').disabled = false;
1173                         break;
1174                 }
1175         }
1176 });
1177
1178 var E2WebCore = Class.create(BaseCore, {
1179         initialize: function($super){
1180                 $super();
1181                 this.mediaPlayerStarted = false;
1182                 this.settings = null;
1183                 this.parentControlList = null;
1184
1185                 this.currentBouquet = bouquetsTv;
1186
1187                 this.updateBouquetItemsPoller = '';
1188                 this.updateCurrentPoller = '';
1189                 this.signalPanelUpdatePoller = '';
1190
1191                 this.isActive = {};
1192                 this.isActive.getCurrent = false;
1193
1194                 this.mode = "";
1195                 this.subMode = "";
1196
1197                 //create required Instances
1198                 this.bouquets = new Bouquets('contentBouquets', 'contentMain');
1199                 this.current = new Current('currentContent', 'volContent');
1200                 this.externals = new Externals('navExternalsContainer');
1201                 this.epg = new EPG(new EpgListHandler());
1202                 this.lt = new LocationsAndTags();
1203                 this.mediaplayer = new MediaPlayer('contentMain');
1204                 this.messages = new Messages();
1205                 this.movies = new Movies('contentMain', 'navContent', 'contentHdExt');
1206                 this.multiepg = new MultiEpg();
1207                 this.power = new Power();
1208                 this.remote = new RemoteControl();
1209                 this.screenshots = new Screenshots('contentMain');
1210                 this.services = new Services('contentServices', this.epg);
1211                 this.signal = new SignalWindow(3);
1212                 this.simplepages = new SimplePages('contentMain');
1213                 this.timers = new Timers('contentMain');
1214                 this.volume = new Volume('volContent');
1215
1216                 this.currentData = {};
1217                 this.currentLocation = "";
1218                 this.currentTag = "";
1219                 this.deviceInfo = "";
1220
1221                 this.navlut = {
1222                         'tv': {
1223                                 'bouquets' : this.bouquets.loadBouquetsTv.bind(this.bouquets),
1224                                 'providers' : this.bouquets.loadProviderTv.bind(this.bouquets),
1225                                 'all' : this.services.loadAllTv.bind(this.services)
1226                                 },
1227                         'radio': {
1228                                 'bouquets' : this.bouquets.loadBouquetsRadio.bind(this.bouquets),
1229                                 'providers' : this.bouquets.loadProviderRadio.bind(this.bouquets),
1230                                 'all' : this.services.loadAllRadio.bind(this.services)
1231                         },
1232                         'movies':{
1233                                 'list' : function(){}
1234                         },
1235                         'timer': {
1236                                 'create' : this.timers.create.bind(this.timers),
1237                                 'edit' : false,
1238                                 'list' : function() { this.loadContentDynamic(this.timers.loadList.bind(this.timers), strings.timers); }.bind(this)
1239                         },
1240                         'control': {
1241                                 'message' : this.simplepages.loadMessage.bind(this.simplepages),
1242                                 'power' : this.simplepages.loadPower.bind(this.simplepages),
1243                                 'osdshot' : this.screenshots.shootOsd.bind(this.screenshots),
1244                                 'screenshot' : this.screenshots.shootAll.bind(this.screenshots),
1245                                 'videoshot' : this.screenshots.shootVideo.bind(this.screenshots)
1246                         },
1247                         'extras': {
1248                                 'about' : this.simplepages.loadAbout.bind(this.simplepages),
1249                                 'deviceinfo' : this.simplepages.loadDeviceInfo.bind(this.simplepages),
1250                                 'mediaplayer' : function() { this.loadContentDynamic(this.mediaplayer.load.bind(this.mediaplayer), strings.mediaplayer); }.bind(this),
1251                                 'settings' : this.simplepages.loadSettings.bind(this.simplepages),
1252                                 'tools' : this.simplepages.loadTools.bind(this.simplepages)
1253                         }
1254                 };
1255         },
1256
1257         delayedUpdateItems: function(){
1258                 var _this = this;
1259                 setTimeout(_this.updateItems.bind(this), 2000);
1260         },
1261
1262         updateItems: function(){
1263                 debug("[E2WebCore].updateItems");
1264                 this.current.load();
1265                 this.power.inStandby(this.onPowerStateAvailable.bind(this));
1266         },
1267
1268         onPowerStateAvailable: function(isStandby){
1269                 if(isStandby){
1270                         $('openSignalPanelImg').src="/web-data/img/transmit_grey.png";
1271                 } else {
1272                         $('openSignalPanelImg').src="/web-data/img/transmit_blue.png";
1273                 }
1274         },
1275
1276         updateItemsLazy: function(){
1277                 debug("[E2WebCore].updateItemsLazy");
1278                 this.services.getNowNext();
1279                 this.services.getSubservices();
1280         },
1281
1282         startUpdateCurrentPoller: function(){
1283                 debug("[E2WebCore].startUpdateCurrentPoller");
1284                 clearInterval(this.updateCurrentPoller);
1285                 var _this = this;
1286                 this.updateCurrentPoller = setInterval(_this.updateItems.bind(this), userprefs.data.updateCurrentInterval);
1287         },
1288
1289         stopUpdateCurrentPoller: function(){
1290                 clearInterval(this.updateCurrentPoller);
1291         },
1292
1293         startUpdateBouquetItemsPoller: function(){
1294                 debug("[E2WebCore].startUpdateBouquetItemsPoller");
1295                 clearInterval(this.updateBouquetItemsPoller);
1296                 var _this = this;
1297                 this.updateBouquetItemsPoller = setInterval(_this.updateItemsLazy.bind(this), userprefs.data.updateBouquetInterval);
1298         },
1299
1300         stopUpdateBouquetItemsPoller: function(){
1301                 debug("[E2WebCore].stopUpdateBouquetItemsPoller");
1302                 clearInterval(this.updateBouquetItemsPoller);
1303         },
1304
1305         setNavHighlight: function(){
1306                 var navitems = $$(".navmenu");
1307                 navitems.each(function(element){
1308                         var mode = element.readAttribute("data-mode");
1309                         var navselected = "navselected";
1310                         if(mode == this.mode){
1311                                 element.addClassName(navselected);
1312                         } else {
1313                                 element.removeClassName(navselected);
1314                         }
1315                 }.bind(this));
1316         },
1317
1318         onHashChanged: function(isReload){
1319                 var hash = hashListener.getHash();
1320                 var parts = hash.split("/");
1321
1322                 var len = parts.length;
1323                 if(len >= 2){
1324                         var mode = parts[1];
1325                         if(mode != this.mode || isReload || ( len <= 2 && this.subMode != '') ){
1326                                 this.switchMode(mode, len == 2);
1327                                 this.subMode = '';
1328                         }
1329                         this.mode = mode;
1330
1331                         this.setNavHighlight();
1332
1333                         if(len > 2){
1334                                 var subMode = parts[2];
1335                                 if(subMode != this.subMode || isReload){
1336                                         this.subMode = subMode;
1337                                         if(!this.navlut[this.mode][this.subMode]){
1338                                                 return;
1339                                         } else {
1340                                                 if(this.mode != "movies")
1341                                                         this.navlut[this.mode][this.subMode]();
1342                                         }
1343                                 }
1344                                 if(len > 3){
1345                                         switch(this.mode){
1346                                         case 'tv':
1347                                         case 'radio':
1348                                                 this.services.load(unescape(parts[3]));
1349                                                 break;
1350                                         case 'movies':
1351                                                 var location = decodeURIComponent(parts[4]);
1352                                                 var tag = decodeURIComponent(parts[5]);
1353
1354                                                 this.currentLocation = location;
1355                                                 this.currentTag = tag;
1356                                                 this.loadContentDynamic(
1357                                                         function(){
1358                                                                 this.movies.load(location, tag);
1359                                                         }.bind(this),
1360                                                         strings.movies,
1361                                                         true
1362                                                 );
1363
1364                                                 break;
1365                                         case 'extras':
1366                                                 if(subMode == 'mediaplayer'){
1367                                                         this.mediaplayer.load(decodeURIComponent(parts[3]));
1368                                                 }
1369                                                 break;
1370                                         default:
1371                                                 return;
1372                                         }
1373                                 }
1374                         }
1375                 }
1376         },
1377
1378         getBaseHash: function(){
1379                 var hash = ['#!', this.mode].join("/");
1380                 if(this.subMode != ''){
1381                         hash = [hash, this.subMode].join("/");
1382                 }
1383                 return hash;
1384         },
1385
1386         loadDefault: function(){
1387                 debug("[E2WebCore].loadDefault");
1388                 this.switchMode('tv');
1389                 this.mode = 'tv';
1390                 this.subMode = 'bouquets';
1391                 this.bouquets.load(bouquetsTv, true);
1392         },
1393
1394         onSessionAvailable: function($super, sid){
1395                 debug("[E2WebCore].onSessionAvailable, " + sid);
1396                 $super(sid);
1397
1398                 this.currentLocation = this.lt.getCurrentLocation(function(location){this.currentLocation = location;}.bind(this));
1399                 this.deviceInfo = this.simplepages.getDeviceInfo(function(info){this.deviceInfo = info;}.bind(this));
1400                 
1401                 if( parseNr(userprefs.data.updateCurrentInterval) < 10000){
1402                         userprefs.data.updateCurrentInterval = 120000;
1403                         userprefs.save();
1404                 }
1405
1406                 if( parseNr(userprefs.data.updateBouquetInterval) < 60000 ){
1407                         userprefs.data.updateBouquetInterval = 300000;
1408                         userprefs.save();
1409                 }
1410
1411                 if (typeof document.body.style.maxHeight == undefined) {
1412                         alert("Due to the tremendous amount of work needed to get everthing to " +
1413                         "work properly, there is (for now) no support for Internet Explorer Versions below 7");
1414                 }
1415                 hashListener.onHashChanged = this.onHashChanged.bind(this);
1416                 hashListener.init();
1417
1418                 this.registerEvents();
1419
1420                 this.setAjaxLoad('navContent');
1421                 this.setAjaxLoad('contentMain');
1422                 
1423                 templateEngine.fetch('tplServiceListEPGItem');
1424                 templateEngine.fetch('tplBouquetsAndServices');
1425                 templateEngine.fetch('tplCurrent');
1426                 if(!hashListener.getHash().length >= 1){
1427                         this.loadDefault();
1428                 }
1429                 this.updateItems();
1430                 this.startUpdateCurrentPoller();
1431         },
1432
1433         registerEvents: function(){
1434                 debug("[E2WebCore].registerEvents");
1435                 //Header
1436                 $('openSignalPanel').on(
1437                         'click',
1438                         function(event, element){
1439                                 this.signal.load();
1440                                 event.stop();
1441                         }.bind(this)
1442                 );
1443                 document.on(
1444                         'click',
1445                         '.doInstantRecord',
1446                         function(event, element){
1447                                 var menu = $('instantRecordMenu');
1448                                 this.timers.recordNow(
1449                                         element.readAttribute('data-type'),
1450                                         function(result){
1451                                                 var toggle = menu.up('.group').down('.dropdown-toggle');
1452                                                 toggle.removeClassName("active");
1453                                                 menu.removeClassName("open");
1454                                                 menu.hide();
1455                                         }
1456                                 );
1457                         }.bind(this)
1458                 );
1459                 //Current
1460                 $('current').on(
1461                         'click',
1462                         '.currentExtShowHide',
1463                         function(event, element){
1464                                 this.current.toggleVisibility(element);
1465                                 event.stop();
1466                         }.bind(this)
1467                 );
1468                 $('current').on(
1469                                 'click',
1470                                 '.currentEpg',
1471                                 function(event, element){
1472                                         var ref = unescape( element.readAttribute('data-servicereference') );
1473                                         this.epg.load(ref);
1474                                         event.stop();
1475                                 }.bind(this)
1476                         );
1477                 //EPG-Search
1478                 $('epgSearchForm').on(
1479                         'submit',
1480                         function(event, element){
1481                                 this.epg.search($F('epgSearch'));
1482                                 event.stop();
1483                         }.bind(this)
1484                 );
1485                 $('epgSearchClear').on(
1486                                 'click',
1487                                 function(event, element){
1488                                         $('epgSearch').value = '';
1489                                         return false;
1490                                 }.bind(this)
1491                 );
1492                 //Movienav
1493                 var changeevt = Prototype.Browser.IE ? "click" : "change";
1494                 var nav = $('navContent');
1495                 nav.on(
1496                         changeevt,
1497                         '.mNavLocTag',
1498                         function(event, element){
1499                                 var l = $('locations');
1500                                 var t = $('tags');
1501                                 var location = l.options[l.selectedIndex].value;
1502                                 var tag = t.options[t.selectedIndex].value;
1503                                 var hash = [this.getBaseHash(), "filter", encodeURIComponent(location), encodeURIComponent(tag)].join("/");
1504                                 if(hash != '#'+hashListener.getHash() || !Prototype.Browser.IE)
1505                                         hashListener.setHash(hash);
1506                         }.bind(this)
1507                 );
1508                 $('contentHdExt').on(
1509                         changeevt,
1510                         '.mNavLocTag',
1511                         function(event, element){
1512                                 var l = $('locations');
1513                                 var t = $('tags');
1514                                 var location = l.options[l.selectedIndex].value;
1515                                 var tag = t.options[t.selectedIndex].value;
1516                                 var hash = [this.getBaseHash(), "filter", encodeURIComponent(location), encodeURIComponent(tag)].join("/");
1517                                 if(hash != '#'+hashListener.getHash() || !Prototype.Browser.IE)
1518                                         hashListener.setHash(hash);
1519                         }.bind(this)
1520                 );
1521                 //RemoteControl
1522                 nav.on(
1523                         'click',
1524                         '.webremote',
1525                         this.remote.open.bind(this.remote)
1526                 );
1527                 //Volume
1528                 $('navVolume').on(
1529                         'click',
1530                         'a.volume',
1531                         function(event, element){
1532                                 this.volume.set(element.readAttribute('data-volume'));
1533                                 return false;
1534                         }.bind(this)
1535                 );
1536
1537                 //Content
1538                 var content = $('contentMain');
1539                 //MediaPlayer
1540                 content.on(
1541                         'click',
1542                         '.mpCmd',
1543                         function(event, element){
1544                                 this.mediaplayer.command(element.readAttribute('data-command'));
1545                         }.bind(this)
1546                 );
1547                 content.on(
1548                         'click',
1549                         '.mpPlayFile',
1550                         function(event, element){
1551                                 var parent = element.up('.mpListItem');
1552                                 var ref = decodeURIComponent( parent.readAttribute('data-servicereference') );
1553                                 this.mediaplayer.playFile(ref);
1554                                 event.stop();
1555                         }.bind(this)
1556                 );
1557                 content.on(
1558                                 'click',
1559                                 '.mpAddFile',
1560                                 function(event, element){
1561                                         var parent = element.up('.mpListItem');
1562                                         var ref = decodeURIComponent( parent.readAttribute('data-servicereference') );
1563                                         this.mediaplayer.addFile(ref);
1564                                         event.stop();
1565                                 }.bind(this)
1566                         );
1567                 content.on(
1568                         'click',
1569                         '.mpRemoveFile',
1570                         function(event, element){
1571                                 var parent = element.up('.mpListItem');
1572                                 var ref = decodeURIComponent( parent.readAttribute('data-servicereference') );
1573                                 this.mediaplayer.removeFile(ref);
1574                                 event.stop();
1575                         }.bind(this)
1576                 );
1577                 content.on(
1578                                 'click',
1579                                 '.mpSavePlaylist',
1580                                 function(event, element){
1581                                         var filename = prompt('Please enter a filename for the playlist', 'playlist');
1582                                         if(filename != null && filename != ""){
1583                                                 this.mediaplayer.savePlaylist(filename);
1584                                         }
1585                                 }.bind(this)
1586                         );
1587                 //Message
1588                 content.on(
1589                         'click',
1590                         '.messageSend',
1591                         function(event, element){
1592                                 var t = $('messageType');
1593                                 text = $('messageText').value;
1594                                 timeout = $('messageTimeout').value;
1595                                 type = t.options[t.selectedIndex].value;
1596                                 this.messages.send(text, type, timeout);
1597                         }.bind(this)
1598                 );
1599                 //Movielist
1600                 content.on(
1601                         'click',
1602                         'a.mListDelete',
1603                         function(event, element){
1604                                 this.movies.del(element);
1605                                 event.stop();
1606                         }.bind(this)
1607                 );
1608                 //Powerstate
1609                 document.on(
1610                         'click',
1611                         '.powerState',
1612                         function(event, element){
1613                                 var newState = element.readAttribute("data-state");
1614                                 var cb = function(isStandby){
1615                                         var text = "Device is now Running";
1616                                         switch(this.power.STATES[newState]){
1617                                         case this.power.STATES.toggle:
1618                                                 if(isStandby)
1619                                                         text = "Device is now in idle mode";
1620                                                 break;
1621                                         case this.power.STATES.deep:
1622                                                 if(isStandby)
1623                                                         text = "Device will go into standby mode (if possible, check OSD for messages)";
1624                                                 else
1625                                                         text = "Cannot shutdown!";
1626                                                 break;
1627                                         case this.power.STATES.reboot:
1628                                                 if(isStandby)
1629                                                         text = "Device will reboot now (if possible, check OSD for messages)";
1630                                                 else
1631                                                         text = "Cannot reboot!";
1632                                                 break;
1633                                         case this.power.STATES.gui:
1634                                                 if(isStandby)
1635                                                         text = "GUI will restart now (if possible, check OSD for messages)";
1636                                                 else
1637                                                         text = "Cannot restart GUI!";
1638                                                 break;
1639                                         }
1640                                         this.notify(text, true);
1641                                         this.onPowerStateAvailable(isStandby);
1642                                 }.bind(this);
1643                                 this.power.set(newState, cb);
1644                         }.bind(this)
1645                 );
1646                 //Settings
1647                 content.on(
1648                         'click',
1649                         '.saveSettings',
1650                         function(event, element){
1651                                 this.saveSettings();
1652                         }.bind(this)
1653                 );
1654                 //Bouquets
1655                 content.on(
1656                         'click',
1657                         'a.bListSLink',
1658                         function(event, element){
1659                                 setContentHd(element.readAttribute("data-servicename"));
1660                         }
1661                 );
1662                 content.on(
1663                         'click',
1664                         'a.bListEpg',
1665                         function(event, element){
1666                                 var sref = decodeURIComponent( element.readAttribute("data-servicereference") );
1667                                 this.multiepg.load(sref);
1668                                 event.stop();
1669                         }.bind(this)
1670                 );
1671
1672                 //Servicelist
1673                 content.on(
1674                         'click',
1675                         'a.sListSLink',
1676                         function(event, element){
1677                                 var ref = decodeURIComponent( element.id );
1678                                 this.services.zap(ref, this.delayedUpdateItems.bind(this));
1679                                 event.stop();
1680                         }.bind(this)
1681                 );
1682                 content.on(
1683                         'click',
1684                         'a.sListServiceEpg',
1685                         function(event, element){
1686                                 var ref = unescape( element.readAttribute('data-servicereference') );
1687                                 this.epg.load(ref);
1688                                 event.stop();
1689                         }.bind(this)
1690                 );
1691                 content.on(
1692                         'click',
1693                         'a.sListExtEpg',
1694                         function(event, element){
1695                                 var target = element.up('.sListEPGItem').down('.sListExtEpgLong');
1696
1697                                 if(target){
1698                                         var bullet = element.down('.sListBulletToggle');
1699                                         if(target.visible()){
1700                                                 target.hide();
1701                                                 bullet.src = "/web-data/img/toggle_expand_small.png";
1702                                                 bullet.alt = "+";
1703                                         } else {
1704                                                 target.show();
1705                                                 bullet.src = "/web-data/img/toggle_collapse_small.png";
1706                                                 bullet.alt = "-";
1707                                         }
1708                                 }
1709                                 event.stop();
1710                         }.bind(this)
1711                 );
1712                 content.on(
1713                         'click',
1714                         '.sListAddTimer',
1715                         function(event, element){
1716                                 core.timers.addByEventId(element, 0);
1717                                 event.stop();
1718                         }
1719                 );
1720                 content.on(
1721                         'click',
1722                         '.sListZapTimer',
1723                         function(event, element){
1724                                 core.timers.addByEventId(element, 1);
1725                                 event.stop();
1726                         }
1727                 );
1728                 content.on(
1729                         'click',
1730                         '.sListEditTimer',
1731                         function(event, element){
1732                                 var hash = ["#!/timer", "edit"].join("/");
1733                                 hashListener.setHash(hash);
1734                                 core.timers.editFromEvent(element);
1735                                 event.stop();
1736                         }
1737                 );
1738
1739                 //Timerlist
1740                 content.on(
1741                         'click',
1742                         '.tListDelete',
1743                         function(event, element){
1744                                 this.timers.del(element);
1745                                 event.stop();
1746                         }.bind(this)
1747                 );
1748                 content.on(
1749                         'click',
1750                         '.tListToggleDisabled',
1751                         function(event, element){
1752                                 this.timers.toggleDisabled(element);
1753                                 event.stop();
1754                         }.bind(this)
1755                 );
1756                 content.on(
1757                         'click',
1758                         '.tListEdit',
1759                         function(event, element){
1760                                 var hash = ["#!/timer", "edit"].join("/");
1761                                 hashListener.setHash(hash);
1762                                 this.timers.edit(element);
1763                                 return false;
1764                         }.bind(this)
1765                 );
1766                 content.on(
1767                         'click',
1768                         '.tListCleanup',
1769                         function(event, element){
1770                                 this.timers.cleanupList();
1771                                 return false;
1772                         }.bind(this)
1773                 );
1774                 //Timer Editing
1775                 content.on(
1776                         'change',
1777                         '.tEditRepeated',
1778                         function(event, element){
1779                                 var days = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su'];
1780                                 var weekdays = days.slice(0,5);
1781
1782                                 switch(element.id){
1783                                 case 'mf':
1784                                         var checked = element.checked;
1785                                         weekdays.each(function(day){
1786                                                 $(day).checked = checked;
1787                                         });
1788                                         if(checked){
1789                                                 var others = ['sa', 'su', 'ms'];
1790                                                 others.each(function(item){
1791                                                         $(item).checked = false;
1792                                                 });
1793                                         }
1794                                         break;
1795                                 case 'ms':
1796                                         var checked = element.checked;
1797                                         days.each(function(day){
1798                                                 $(day).checked = checked;
1799                                         });
1800                                         if(checked){
1801                                                 $('mf').checked = false;
1802                                         }
1803                                         break;
1804                                 default:
1805                                         var weekdays = true;
1806                                         var alldays = true;
1807                                         days.each(function(day){
1808                                                 day = $(day);
1809                                                 if(day.value <= 64){
1810                                                         if(!day.checked){
1811                                                                 alldays = false;
1812                                                                 if(day.value <= 16){
1813                                                                         weekdays = false;
1814                                                                         return
1815                                                                 }
1816                                                         } else {
1817                                                                 if(day.value > 16){
1818                                                                         weekdays = false;
1819                                                                 }
1820                                                         }
1821                                                 }
1822                                         });
1823                                         if(alldays){
1824                                                 $('mf').checked = false;
1825                                                 $('ms').checked = true;
1826                                         } else if (weekdays) {
1827                                                 $('mf').checked = true;
1828                                                 $('ms').checked = false;
1829                                         } else {
1830                                                 $('mf').checked = false;
1831                                                 $('ms').checked = false;
1832                                         }
1833                                 }
1834                         }
1835                 );
1836                 content.on(
1837                         'change',
1838                         '.tEditBouquet',
1839                         function(event, element){
1840                                 var value = unescape( element.options[element.selectedIndex].value );
1841                                 core.timers.onBouquetChanged(value);
1842                         }.bind(this)
1843                 );
1844                 content.on(
1845                         'click',
1846                         '.tEditTag',
1847                         function(event, element){
1848                                 var selected = 'selected';
1849                                 var attr = 'data-selected';
1850                                 if(element.hasClassName(selected)){
1851                                         element.removeClassName(selected);
1852                                         element.writeAttribute(attr, '');
1853                                 } else {
1854                                         element.addClassName(selected);
1855                                         element.writeAttribute(attr, selected);
1856                                 }
1857                                 event.stop();
1858                         }.bind(this)
1859                 );
1860                 content.on(
1861                         'click',
1862                         '.tEditSave',
1863                         function(event, element){
1864                                 this.timers.save($('timerEditForm'));
1865                         }.bind(this)
1866                 );
1867
1868                 $('webTv').on(
1869                         'click',
1870                         function(event, element){
1871                                 window.open('/web-data/tpl/default/streaminterface/index.html', 'WebTV', 'scrollbars=no, width=800, height=740, resizable=yes');
1872                                 event.stop();
1873                         }.bind(this)
1874                 );
1875                 //Hash-Reload-Fix
1876                 //HACK :: THIS IS EVIL VOODOO, DON'T TRY THIS AT HOME!
1877                 document.on(
1878                         'click',
1879                         'a',
1880                         function(event, element){
1881                                 if(event.stopped)
1882                                         return;
1883                                 var parts = element.href.split('#');
1884                                 var curHost = window.location.href.split('#')[0];
1885                                 //Don't do this crazy stuff when the target is another host!
1886                                 if(curHost == parts[0]){
1887                                         if (parts.length > 1){
1888                                                 if(parts[1] != ''){
1889                                                         if(window.location == element.href){
1890                                                                 this.onHashChanged(true);
1891                                                                 return;
1892                                                         }else{
1893                                                                 window.location == element.href;
1894                                                                 return;
1895                                                         }
1896                                                 } else {
1897                                                         element.href = window.location;
1898                                                 }
1899                                                 return;
1900                                         }
1901                                 }
1902                         }.bind(this)
1903                 );
1904         },
1905
1906         /*
1907          * Loads another navigation template and sets the navigation header
1908          * @param template - The name of the template
1909          * @param title - The title to set for the navigation
1910          */
1911         reloadNav: function(template, title, callback){
1912                 this.setAjaxLoad('navContent');
1913                 templateEngine.process(template, null, 'navContent', callback);
1914                 setNavHd(title);
1915         },
1916
1917         reloadNavDynamic: function(fnc, title){
1918                 this.setAjaxLoad('navContent');
1919                 setNavHd(title);
1920                 fnc();
1921         },
1922
1923         /*
1924          * Loads dynamic content to $(contentMain) by calling a execution function
1925          * @param fnc - The function used to load the content
1926          * @param title - The Title to set on the contentpanel
1927          */
1928         loadContentDynamic: function(fnc, title, keepHdExt){
1929                 setContentHd(title, keepHdExt);
1930                 this.stopUpdateBouquetItemsPoller();
1931                 fnc();
1932         },
1933
1934         /*
1935          * Loads a static template to $(contentMain)
1936          * @param template - Name of the Template
1937          * @param title - The Title to set on the Content-Panel
1938          */
1939         loadContentStatic: function(template, title){
1940                 this.setAjaxLoad('contentMain');
1941                 setContentHd(title);
1942                 this.stopUpdateBouquetItemsPoller();
1943                 templateEngine.process(template, null, 'contentMain');
1944         },
1945
1946         setEmptyContent: function(id, text){
1947                 $(id).update('<div class="block center fullwidth oneliner">' + text + '</div>');
1948         },
1949
1950         switchMode: function(mode, initContent){
1951                 if(initContent){
1952                         this.setEmptyContent('contentMain', strings.select_submenu);
1953                         setContentHd('...');
1954                 }
1955
1956                 switch(mode){
1957                 case "tv":
1958                         if(this.mode != 'tv' && this.mode != 'radio'){
1959                                 this.services.registerEvents();
1960                         }
1961                         this.reloadNav('tplNavTv', strings.television);
1962                         break;
1963
1964                 case "radio":
1965                         if(this.mode != 'tv' && this.mode != 'radio'){
1966                                 this.services.registerEvents();
1967                         }
1968                         this.reloadNav('tplNavRadio', strings.radio);
1969                         break;
1970
1971                 case "movies":
1972                         this.reloadNavDynamic(this.movies.loadNav.bind(this.movies), strings.movies);
1973                         break;
1974
1975                 case "timer":
1976                         this.reloadNav('tplNavTimer', strings.timers);
1977                         break;
1978
1979                 case "control":
1980                         this.reloadNav('tplNavBoxControl', strings.boxcontrol);
1981                         break;
1982
1983                 case "extras":
1984                         this.reloadNav('tplNavExtras', strings.extras, this.externals.load.bind(this.externals));
1985                         break;
1986
1987                 default:
1988                         break;
1989                 }
1990         },
1991
1992         saveSettings: function(){
1993                 userprefs.load();
1994                 var changed = false;
1995
1996                 var l = $('interfaceStyle');
1997                 var style = l.options[l.selectedIndex].value;
1998                 if(style != userprefs.data.style){
1999                         userprefs.data.style = style;
2000                         changed = true;
2001                         this.styleChanged();
2002                 }
2003                 
2004                 var debug = $('enableDebug').checked;
2005                 if(debug != undefined){
2006                         if( userprefs.data.debug != debug ){
2007                                 userprefs.data.debug = debug;
2008                                 changed = true;
2009                         }
2010                 }
2011
2012                 var updateCurrentInterval = parseNr( $F('updateCurrentInterval') ) * 1000;
2013                 if( updateCurrentInterval < 10000){
2014                         updateCurrentInterval = 120000;
2015                 }
2016
2017                 if( userprefs.data.updateCurrentInterval != updateCurrentInterval){
2018                         userprefs.data.updateCurrentInterval = updateCurrentInterval;
2019                         changed = true;
2020                         this.startUpdateCurrentPoller();
2021                 }
2022
2023                 var updateBouquetInterval = parseNr( $F('updateBouquetInterval') ) * 1000;
2024                 if( updateBouquetInterval < 60000){
2025                         updateBouquetInterval = 300000;
2026                 }
2027
2028                 if( userprefs.data.updateBouquetInterval != updateBouquetInterval){
2029                         userprefs.data.updateBouquetInterval = updateBouquetInterval;
2030
2031                         changed = true;
2032                         this.startUpdateBouquetItemsPoller();
2033                 }
2034
2035                 if(changed){
2036                         userprefs.save();
2037                         this.notify("Settings saved");
2038                 } else {
2039                         this.notify("Nothing changed! No need to save!");
2040                 }
2041         }
2042 });
2043
2044 DropDownHandler = Class.create({
2045         initialize: function(){
2046                 this.registerEvents();
2047         },
2048
2049         show: function(toggle, menu){
2050                 toggle.addClassName("active");
2051                 menu.addClassName("open");
2052                 menu.show();
2053         },
2054
2055         hide: function(toggle, menu){
2056                 toggle.removeClassName("active");
2057                 menu.removeClassName("open");
2058                 menu.hide();
2059         },
2060
2061         onClick: function(event, toggle){
2062                 event.stop();
2063                 var menu = toggle.up('.group').down('.dropdown-menu');
2064                 if(menu.visible()){
2065                         this.hide(toggle, menu);
2066                 } else {
2067                         this.show(toggle, menu)
2068                 }
2069         },
2070
2071         registerEvents: function(){
2072                 document.on(
2073                         'click',
2074                         '.dropdown-toggle',
2075                         this.onClick.bind(this)
2076                 );
2077                 document.on(
2078                         'click',
2079                         function(event, element){
2080                                 if(event.stopped)
2081                                         return;
2082                                 $$('.open').each(function(menu){
2083                                         if(element != menu && element.up('.open') != menu){
2084                                                 var toggle = menu.up('.group').down('.dropdown-toggle');
2085                                                 this.hide(toggle, menu);
2086                                         }
2087                                 }.bind(this));
2088                         }.bind(this)
2089                 );
2090         }
2091 });
2092
2093 var dropDownHandler = new DropDownHandler();
2094
2095 var core = new E2WebCore();