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