AutoTimer WebIf: If the user runs a Preview, clear the autotimer list selection
[enigma2-plugins.git] / autotimer / src / web-data / autotimereditor.js
1 ///////////////////////////////////////////////////////////////////////////////
2 // Global variables
3 //TODO remove globals
4 //var currentAutoTimerListIndex = null;
5 //var currentAutoTimerList = [];
6 //TODO var currentAutoTimer = null;
7
8
9 ///////////////////////////////////////////////////////////////////////////////
10 // Statics
11 function url() {
12         this.tpl              = '';
13         this.editor           = '/autotimereditor';
14         this.backup           = '/autotimereditor/web/backup';
15         this.restore          = '/autotimereditor/web/restore';
16         this.list             = '/autotimer';
17         this.get              = '/autotimer/get';
18         this.set              = '/autotimer/set';
19         this.edit             = '/autotimer/edit';
20         this.add              = '/autotimer/edit';
21         this.remove           = '/autotimer/remove';
22         this.parse            = '/autotimer/parse';
23         this.preview          = '/autotimer/simulate';
24         this.tmp              = '/autotimereditor/tmp/';
25         this.getservices      = '/web/getservices';
26 };
27 var URL = new url();
28
29 var types = {};
30 types['include'] = 'Include';
31 types['exclude'] = 'Exclude';
32
33 var wheres = {};
34 wheres['title'] = 'Title';
35 wheres['shortdescription'] = 'Short description';
36 wheres['description'] = 'Description';
37 wheres['dayofweek'] = 'Day of week';
38
39 var weekdays = {};
40 weekdays['0'] = 'Monday';
41 weekdays['1'] = 'Tuesday';
42 weekdays['2'] = 'Wednesday';
43 weekdays['3'] = 'Thursday';
44 weekdays['4'] = 'Friday';
45 weekdays['5'] = 'Saturday';
46 weekdays['6'] = 'Sunday';
47 weekdays['weekend'] = 'Weekend';
48 weekdays['weekday'] = 'Weekday';
49
50 ///////////////////////////////////////////////////////////////////////////////
51 // Global functions
52 function compareStrings(a, b){
53         a = a.toLowerCase();
54         b = b.toLowerCase();
55         return (b < a) - (a < b);
56 }
57
58 function sortAutoTimer(a,b){
59         return compareStrings(a.name, b.name);
60 }
61
62 function in_array(a,p){
63         for (i=0;i<a.length;i++)
64                 if (a[i] == p) return true
65         return false
66 }
67
68 function toReadableDate(date){
69         var dateString = "";
70         dateString += date.getFullYear();
71         dateString += "-" + addLeadingZero(date.getMonth()+1);
72         dateString += "-" + addLeadingZero(date.getDate());
73         return dateString;
74 }
75
76 function toReadableDateTime(date){
77         var dateString = "";
78         dateString += date.getFullYear();
79         dateString += "-" + addLeadingZero(date.getMonth()+1);
80         dateString += "-" + addLeadingZero(date.getDate());
81         dateString += " " + addLeadingZero(date.getHours());
82         dateString += ":" + addLeadingZero(date.getMinutes());
83         return dateString;
84 }
85
86 function toTimestamp(date){
87                 date = date.split('-');
88                 var sDate = new Date();
89                 sDate.setFullYear(date[0], date[1] - 1, date[2]);
90                 sDate.setHours( 0 );
91                 sDate.setMinutes( 0 );
92                 sDate.setSeconds( 0 );
93                 return Math.floor(sDate.getTime() / 1000);
94 }
95
96 function createOptionList(object, selected) {
97         var namespace = Array();
98         var i = 0;
99         for ( var element in object) {
100                 var txt = String(object[element]);
101                 var sel = " ";
102
103                 if (element == selected) {
104                         sel = "selected";
105                 }
106
107                 if (element != "extend") {
108                         namespace[i] = {
109                                 'value' : element,
110                                 'txt' : txt,
111                                 'selected' : sel
112                         };
113                         i++;
114                 }
115         }
116         return namespace;
117 }
118
119 function numericalOptionList(lowerBound, upperBound, selectedValue, offset){
120         var list = [];
121         var idx = 0;
122         if(offset == undefined){
123                 offset = 0;
124         }
125         
126         for(var i = lowerBound; i <= upperBound; i++){
127                 var t = i + offset;
128                 var txt = t < 10 ? "0" + t : t;
129                 var selected = "";
130                 if(i == selectedValue){
131                         selected = 'selected';
132                 }
133                 list[idx] = {value : i, txt : txt, selected : selected};
134                 idx++;
135         }
136         return list;
137 }
138
139 function getAttribute(xml, key, defaults){
140         var value = xml.getAttribute(key);
141         if (value==undefined) {
142                 if (key in defaults){
143                         value = defaults[key];
144                 }
145         }
146         return value;
147 }
148
149
150 ///////////////////////////////////////////////////////////////////////////////
151 // AutoTimerEditorCore
152 var AutoTimerEditorCore = Class.create({
153         initialize: function(){
154                 // Instantiate all elements
155                 this.services = new AutoTimerServiceController();
156                 this.settings = new AutoTimerSettingsController
157                 
158                 this.menu = new AutoTimerMenuController('contentAutoTimerMenu');
159                 this.list = new AutoTimerListController('contentAutoTimerList');
160                 this.edit = new AutoTimerEditController('contentAutoTimerContent');
161                 this.preview = new AutoTimerPreviewController('contentAutoTimerContent');
162                 
163                 // Display menu
164                 this.menu.load();
165                 
166                 // Start loading
167                 this.loadFirst();
168         },
169         
170         loadFirst: function(){
171                 // At first load locations and tags
172                 core.lt.getLocationsAndTags(this.loadLocationsAndTagsCallback.bind(this));
173         },
174         
175         loadLocationsAndTagsCallback: function(currentLocation, locations, tags){
176                 this.currentLocation = currentLocation;
177                 this.locations = locations;
178                 this.tags = tags;
179                 this.loadSecond();
180         },
181         
182         loadSecond: function(){
183                 // At second load bouquet list
184                 this.services.loadBouquetsTv(this.loadBouquetsCallback.bind(this));
185         },
186         
187         loadBouquetsCallback: function(bouquets){
188                 this.bouquets = bouquets;
189                 this.loadThird();
190         },
191         
192         loadThird: function(){
193                 // At third load autotimer settings
194                 this.settings.load(this.loadSettingsCallback.bind(this));
195         },
196         
197         loadSettingsCallback: function(settings){
198                 this.hasVps = settings['hasVps'];
199                 this.loadFourth();
200         },
201         
202         loadFourth: function(){
203                 // At fourth load and display autotimer list
204                 this.list.load();
205         },
206 });
207
208
209 ///////////////////////////////////////////////////////////////////////////////
210 // Controller
211 var AutoTimerServiceController = Class.create(Controller, {
212         initialize: function($super){
213                 $super(new AutoTimerServiceListHandler());
214         },
215         
216         load: function(sRef, callback){
217                 this.handler.load( {'sRef' : sRef}, callback );
218         },
219         
220         loadBouquetsTv: function(callback){
221                 this.load(bouquetsTv, callback);
222         },
223         
224         onFinished: function(){
225         },
226         
227         registerEvents: function(){
228         }
229 });
230
231 var AutoTimerSettingsController = Class.create(Controller, {
232         initialize: function($super){
233                 $super(new AutoTimerSettingsHandler());
234         },
235         
236         load: function(callback){
237                 this.handler.load( callback );
238         },
239         
240         onFinished: function(){
241         },
242         
243         registerEvents: function(){
244         }
245 });
246
247 var AutoTimerMenuController  = Class.create(Controller, {
248         initialize: function($super, target){
249                 $super(new AutoTimerMenuHandler(target));
250         },
251         
252         back: function(){
253                 window.location = window.location.origin;
254         },
255         
256         load: function(){
257                 this.handler.load({});
258         },
259         
260         preview: function(){
261                 autotimereditorcore.preview.load();
262         },
263         
264         backup: function() {
265                 this.filename=prompt('Please enter filename for backup file:', 'autotimer_backup');
266                 if (this.filename) {
267                         this.handler.backup(
268                                 { 'Filename' : this.filename },
269                                 this.download.bind(this));
270                 }
271                 
272         },
273         download: function(file){
274                 var url =  URL.tmp + file;
275                 window.open(url,'Download');
276                 core.notify("Downloading...");
277         },
278         
279         restore: function(){
280                 this.upload();
281         },
282         
283         upload: function(){
284                 //TODO move to a separate class
285                 var form = $('backupform');
286                 
287                 if($('file').value.trim() == ""){
288                         core.notify("Please select a File to restore!");
289                         return;
290                 }
291                 // Create the iframe...
292                 var iframe = document.createElement("iframe");
293                 iframe.setAttribute("id","upload_iframe");
294                 iframe.setAttribute("name","upload_iframe");
295                 iframe.setAttribute("width","0");
296                 iframe.setAttribute("height","0");
297                 iframe.setAttribute("border","0");
298                 iframe.setAttribute("style","width: 0; height: 0; border: none;");
299         
300                 // Add to document...
301                 form.parentNode.appendChild(iframe);
302                 window.frames['upload_iframe'].name="upload_iframe";
303                 iframe = $(iframe);
304         
305                 // Add event...
306                 var eventHandler = function(){
307                         // Message from server...
308                         var resdoc;
309                         
310                         if (iframe.contentDocument) {
311                                         resdoc = iframe.contentDocument;
312                         } else if (iframe.contentWindow) {
313                                         resdoc = iframe.contentWindow.document;
314                         } else if (iframe.document) {
315                                         resdoc = iframe.document;
316                         }
317         
318                         var result = new SimpleXMLResult(resdoc);
319                         if (result.getState()){
320                                 autotimereditorcore.menu.handler.restore(
321                                         { 'Filename' : result.getStateText() },
322                                         autotimereditorcore.menu.uploadCallback.bind(this));
323                         } else {
324                                 core.notify( result.getStateText() );
325                         }
326         
327                         try{
328                                 // unregister Eventhandler
329                                 iframe.stopObserving();
330                                 // remove iframe
331                                 iframe.parentNode.removeChild(iframe);
332                         } catch(e){alert(e);}
333                 }
334         
335                 iframe.observe("load", eventHandler);
336                 // Set properties of form...
337                 form.setAttribute("target","upload_iframe");
338                 //form.setAttribute("action", action_url);
339                 form.setAttribute("action", "uploadfile");
340                 form.setAttribute("method","post");
341                 form.setAttribute("enctype","multipart/form-data");
342                 form.setAttribute("encoding","multipart/form-data");
343         
344                 // Submit the form...
345                 form.submit();
346         
347                 core.notify("Uploading...");
348         },
349         uploadCallback: function(){
350                 autotimereditorcore.list.reload();
351         },
352         
353         registerEvents: function(){
354                 $('back').on(
355                         'click',
356                         function(event, element){
357                                 this.back();
358                         }.bind(this)
359                 );
360                 $('back').title = "Back to Dreambox Webcontrol";
361                 $('reload').on(
362                         'click',
363                         function(event, element){
364                                 autotimereditorcore.list.reload();
365                         }.bind(this)
366                 );
367                 $('reload').title = "Reload the AutoTimer list";
368                 $('parse').on(
369                         'click',
370                         function(event, element){
371                                 autotimereditorcore.list.parse();
372                         }.bind(this)
373                 );
374                 $('parse').title = "Run AutoTimer and add timer";
375                 $('preview').on(
376                         'click',
377                         function(event, element){
378                                 this.preview();
379                         }.bind(this)
380                 );
381                 $('preview').title = "Simulate and show the matching timer";
382                 $('backup').on(
383                         'click',
384                         function(event, element){
385                                 this.backup();
386                         }.bind(this)
387                 );
388                 $('backup').title = "Backup the AutoTimer configuration";
389                 $('restore').on(
390                         'click',
391                         function(event, element){
392                                 this.restore();
393                         }.bind(this)
394                 );
395                 $('restore').title = "Restore a previous backuped AutoTimer configuration";
396         },
397 });
398
399 var AutoTimerListController = Class.create(Controller, {
400         //TODO What about a clone AutoTimer function
401         initialize: function($super, target){
402                 $super(new AutoTimerListHandler(target));
403                 this.select = null;
404         },
405         
406         load: function(){
407                 this.handler.load({});
408         },
409         
410         onFinished: function(){
411                 this.onChange();
412         },
413         
414         onChange: function(){
415                 var selectList = $('list');
416                 var selectOptions = selectList.getElementsByTagName('option');
417                 if ( selectOptions.length > 0){
418                         if (this.select != null){
419                                 // Select the given AutoTimer because of add/remove action
420                                 for (idx in selectOptions){
421                                         if ( this.select == unescape(selectOptions[idx].value) ){
422                                                 selectOptions[idx].selected = true;
423                                                 break;
424                                         }
425                                 }
426                                 this.select = null;
427                         }
428                         var idx = selectList.selectedIndex;
429                         if (idx < 0){
430                                 // Select at least the first element
431                                 idx = 0;
432                                 selectOptions[idx].selected = true;
433                         }
434
435                         // Update editor
436                         var id = unescape(selectList.options[idx].value); 
437                         autotimereditorcore.edit.load( id );
438                 } else if (selectOptions.length == 0){
439                         //TODO TEST we should see an empty editor page?
440                 }
441         },
442         
443         reload: function(){
444                 this.select = $('list').value;
445                 this.load();
446         },
447         
448         parse: function(){
449                 this.handler.parse({}, this.reload.bind(this));
450         },
451         
452         add: function(){
453                 this.match = prompt("Name des AutoTimers:");
454                 if (this.match.length){
455                         var selectList = $('list');
456                         var selectOptions = selectList.getElementsByTagName('option');
457                         // Retrieve next selected entry
458                         this.select = selectOptions.length+1;
459                         // Add new AutoTimer: Use edit without an id
460                         this.handler.add( 
461                                 {'match' : this.match},
462                                 function(request){
463                                         this.load();
464                                 }.bind(this));
465                 }
466         },
467         
468         remove: function(){
469                 var selectList = $('list');
470                 var selectOptions = selectList.getElementsByTagName('option');
471                 var idx = selectList.selectedIndex; 
472                 var id = unescape(selectOptions[idx].value);
473                 // Retrieve next selected entry
474                 if ( selectOptions.length > 0){
475                         if ( selectOptions.length > (idx+1)){
476                                 this.select = unescape(selectOptions[idx+1].value);
477                         } else if ( (idx-1) > 0 ){
478                                 this.select = unescape(selectOptions[idx-1].value);
479                         }
480                 }
481                 var check = confirm("Do you really want to delete the AutoTimer\n" + selectList.options[idx].text + " ?");
482                 if (check == true){
483                         this.handler.remove(
484                                 {'id' : id},
485                                 function(request){
486                                         this.load();
487                                 }.bind(this));
488                 }
489         },
490         
491         registerEvents: function(){
492                 $('list').on(
493                         'change',
494                         function(event, element){
495                                 this.onChange();
496                         }.bind(this)
497                 );
498                 $('add').on(
499                         'click',
500                         function(event, element){
501                                 this.add();
502                         }.bind(this)
503                 );
504                 $('delete').on(
505                         'click',
506                         function(event, element){
507                                 this.remove();
508                         }.bind(this)
509                 );
510         }
511 });
512
513 var AutoTimerEditController = Class.create(Controller, {
514         initialize: function($super, target){
515                 $super(new AutoTimerEditHandler(target));
516         },
517         
518         load: function( id ){
519                 this.id = id;
520                 this.handler.load( id );
521         },
522         
523         reload: function(){
524                 this.handler.load( this.id );
525         },
526         
527         onFinished: function(){
528                 this.onchangeSelect( $('justplay') );
529                 this.onchangeCheckbox( $('timespan') );
530                 this.onchangeCheckbox( $('timeframe') );
531                 this.onchangeCheckbox( $('offset') );
532                 this.onchangeCheckbox( $('maxdurationavailable') );
533                 this.onchangeCheckbox( $('locationavailable') );
534                 this.onchangeSelectAfterEvent( $('afterevent') );
535                 this.onchangeSelect( $('counter') );
536                 this.onchangeCheckbox( $('usefilters') );
537                 var filterwheres = $$('.filterwhere');
538                 for (var i = 0; i < filterwheres.size(); i++) {
539                         this.onchangeSelectFilter(filterwheres[i]);
540                 }
541                 this.onchangeCheckbox( $('usebouquets') );
542                 this.onchangeCheckbox( $('useservices') );
543                 var services = $$('.service');
544                 for (var i = 0; i < services.size(); i++) {
545                         if (services[i].lastElementChild.className == 'add'){
546                                 this.onchangeSelectBouquet(services[i].firstElementChild.firstElementChild);
547                         }
548                 }
549                 this.onchangeCheckbox( $('vps_enabled') );
550                 
551                 AnyTime.noPicker( 'from' );
552                 AnyTime.picker( 'from', { format: "%H:%i" } );
553                 AnyTime.noPicker( 'to' );
554                 AnyTime.picker( 'to', { format: "%H:%i" } );
555                 AnyTime.noPicker( 'after' );
556                 AnyTime.picker( 'after', { format: "%Y-%m-%d", firstDOW: 1 } );
557                 AnyTime.noPicker( 'before' );
558           AnyTime.picker( 'before', { format: "%Y-%m-%d", firstDOW: 1 } );
559                 AnyTime.noPicker( 'aftereventFrom' );
560                 AnyTime.picker( 'aftereventFrom', { format: "%H:%i" } );
561                 AnyTime.noPicker( 'aftereventTo' );
562                 AnyTime.picker( 'aftereventTo', { format: "%H:%i" } );
563         },
564         
565         onchangeCheckbox: function(x) {
566                 if (x.checked){
567                         $(x.id+'content').style.display = 'block';
568                 } else{
569                         $(x.id+'content').style.display = 'none';
570                 }
571         },
572         
573         onchangeSelect: function(x) {
574                 if (x.value > 0){
575                         $(x.id+'content').style.display = 'block';
576                 } else{
577                         $(x.id+'content').style.display = 'none';
578                 }
579         },
580         
581         onchangeSelectAfterEvent: function(x) {
582                 if (x.value == 'default'){
583                         $('aftereventusetimespan').checked = '';
584                         $(x.id+'content').style.visibility = "hidden";
585                 } else{
586                         $(x.id+'content').style.visibility = 'visible';
587                 }
588                 this.onchangeCheckbox( $('aftereventusetimespan') );
589         },
590         
591         onchangeSelectFilter: function(x) {
592                 if (x.value == 'dayofweek'){
593                         x.parentNode.nextElementSibling.children[0].style.display = 'none';
594                         x.parentNode.nextElementSibling.children[1].style.display = 'block';
595                 } else{
596                         x.parentNode.nextElementSibling.children[1].style.display = 'none';
597                         x.parentNode.nextElementSibling.children[0].style.display = 'block';
598                 }
599         },
600         
601         onchangeSelectBouquet: function(x) {
602                 // Load services of selected bouquet
603                 var service = unescape(x.value);
604                 autotimereditorcore.services.load( service, this.loadServicesCallback.bind(this, x) );
605         },
606         
607         loadServicesCallback: function(x, services) {
608                 var select = x.parentNode.nextElementSibling.firstElementChild;
609                 for (i = select.options.length - 1; i>=0; i--) {
610                         select.options.remove(i);
611                 }
612                 for ( var service in services) {
613                         select.options.add( new Option(String(services[service]), service ) );
614                 }
615         },
616         
617         changeTag: function(x) {
618                 var selected = 'selected';
619                 var attr = 'data-selected';
620                 if(x.hasClassName(selected)){
621                         x.removeClassName(selected);
622                         x.writeAttribute(attr, '');
623                 } else {
624                         x.addClassName(selected);
625                         x.writeAttribute(attr, selected);
626                 }
627         },
628         
629         addFilter: function(x) {
630                 var parent = x.parentNode;
631                 if (parent.children[1].firstElementChild.value == 'dayofweek' || parent.children[2].firstElementChild.value){
632                         var node = parent.cloneNode(true);
633                         node.children[0].firstElementChild.selectedIndex = parent.children[0].firstElementChild.selectedIndex;
634                         node.children[1].firstElementChild.selectedIndex = parent.children[1].firstElementChild.selectedIndex;
635                         node.children[2].firstElementChild.value = parent.children[2].firstElementChild.value;
636                         node.children[2].lastElementChild.selectedIndex = parent.children[2].lastElementChild.selectedIndex;
637                         node.children[3].className = 'remove';
638                         $('filterlist').firstElementChild.insertBefore(node, parent);
639                 }
640         },
641         
642         removeFilter: function(x) {
643                 var parent = x.parentNode;
644                 var element = parent.children[0].firstElementChild;
645                 var text = element.options[element.selectedIndex].text;
646                 element = parent.children[1].firstElementChild;
647                 text += ' ' + element.options[element.selectedIndex].text;
648                 if (element.value == 'dayofweek'){
649                         element = parent.children[2].lastElementChild;
650                         text += ' ' + element.options[element.selectedIndex].text;
651                 } else{
652                         text += ' ' + parent.children[2].firstElementChild.value;
653                 }
654                 var check = confirm("Do you really want to remove the Filter\n" + text + " ?");
655                 if (check == true){
656                         $('filterlist').deleteRow(parent.rowIndex); 
657                 }
658         },
659
660         addBouquet: function(x) {
661                 var parent = x.parentNode;
662                 var node = parent.cloneNode(true);
663                 node.children[0].firstElementChild.selectedIndex = parent.children[0].firstElementChild.selectedIndex;
664                 node.children[1].className = 'remove';
665                 $('bouquetlist').firstElementChild.insertBefore(node, parent);
666         },
667         
668         removeBouquet: function(x) {
669                 var parent = x.parentNode;
670                 var element = parent.children[0].firstElementChild;
671                 var text = element.options[element.selectedIndex].text;
672                 var check = confirm("Do you really want to remove the Bouquet\n" + text + " ?");
673                 if (check == true){
674                         $('bouquetlist').deleteRow(parent.rowIndex); 
675                 }
676         },
677                 
678         addService: function(x) {
679                 var parent = x.parentNode;
680                 var node = parent.cloneNode(true);
681                 // Check if service is not a marker
682                 // Service reference flags == isMarker (== 64)
683                 var reference = parent.children[1].firstElementChild.value;
684                 if (unescape(reference).slice(2,4) != "64"){
685                         node.children[0].firstElementChild.selectedIndex = parent.children[0].firstElementChild.selectedIndex;
686                         node.children[1].firstElementChild.selectedIndex = parent.children[1].firstElementChild.selectedIndex;
687                         node.children[2].className = 'remove';
688                         $('servicelist').firstElementChild.insertBefore(node, parent);
689                 }
690         },
691         
692         removeService: function(x) {
693                 var parent = x.parentNode;
694                 var element = parent.children[1].firstElementChild;
695                 var text = element.options[element.selectedIndex].text;
696                 var check = confirm("Do you really want to remove the Service\n" + text + " ?");
697                 if (check == true){
698                         $('servicelist').deleteRow(parent.rowIndex); 
699                 }
700         },
701         
702         save: function() {
703                 //TODO Move to a separate class similar AutoTimerListEntry
704                 //TODO handle defaults
705                 var data = {}
706                 var selectList = $('list');
707                 var idx = selectList.selectedIndex;
708                 data['id'] = unescape(selectList.options[idx].value);
709                 
710                 data['enabled'] = ($('enabled').checked) ? '1' : '0';
711                 
712                 options = ['match','name','encoding','searchType','searchCase','justplay','avoidDuplicateDescription'];
713                 for (var id = 0; id < options.length; id++) {
714                         if ($(options[id]).value == ''){
715                                 notify('Error: ' + options[id] + ' is empty', false);
716                                 return;
717                         }
718                         data[options[id]] = $(options[id]).value;
719                 }
720                 
721                 if ($('justplay').value > 0){
722                                 data['setEndtime']            = ($('setEndtime').checked) ? '1' : '0';
723                 }
724                 
725                 data['overrideAlternatives'] = ($('overrideAlternatives').checked) ? '1' : '0';
726                 
727                 if ($('timespan').checked){
728                         options = ['from','to'];
729                         for (var id = 0; id < options.length; id++) {
730                                 if ($(options[id]).value == ''){
731                                         notify('Error: ' + options[id] + ' is empty', false);
732                                         return;
733                                 }
734                         }
735                         //WHY do we have to use timespanFrom instead of from?
736                         data['timespanFrom']            = $('from').value;
737                         data['timespanTo']              = $('to').value;
738                 } else{
739                         data['timespanFrom']            = '';
740                         data['timespanTo']              = '';
741                 }
742                 
743                 if ($('timeframe').checked){
744                         options = ['before','after'];
745                         for (var id = 0; id < options.length; id++) {
746                                 if ($(options[id]).value == ''){
747                                         notify('Error: ' + options[id] + ' is empty', false);
748                                         return;
749                                 }
750                         }
751                         data['before'] = toTimestamp($('before').value).toString();
752                         data['after']  = toTimestamp($('after').value).toString();
753                 } else{
754                         data['before']             = '';
755                         data['after']              = '';
756                 }
757                 
758                 if ($('offset').checked){
759                         if ($('offset').value == ''){
760                                 notify('Error: offset is empty', false);
761                                 return;
762                         }
763                         data['offset']                  = $('offsetbegin').value + ',' + $('offsetend').value;
764                 } else{
765                         data['offset']             = '';
766                 }
767                 
768                 if ($('maxdurationavailable').checked){
769                         if ($('maxduration').value == ''){
770                                 notify('Error: maxduration is empty', false);
771                                 return;
772                         }
773                         data['maxduration']             = $('maxduration').value;
774                 } else{
775                         data['maxduration']             = '';
776                 }
777                 
778                 var afterevent = $('afterevent').value;
779                 data['afterevent']              = afterevent;
780                 if ($('aftereventusetimespan').checked){
781                         data['aftereventFrom']        = $('aftereventFrom').value;
782                         data['aftereventTo']          = $('aftereventTo').value;
783                 }
784
785                 data['counter']                 = $('counter').value;           
786                 if ($('counter').value > 0){
787                         data['counterFormat']           = $('counterFormat').value;
788                         data['left']                    = $('left').value;
789                         var lastActivation = $('lastActivation').value;
790                         if (lastActivation) data['lastActivation'] = lastActivation;
791                         var lastBegin = $('lastBegin').value;
792                         if (lastBegin) data['lastBegin'] = lastBegin;
793                 }
794                 
795                 if ($('locationavailable').checked){
796                         if ($('location').value == ''){
797                                 notify('Error: location is empty', false);
798                                 return;
799                         }
800                         data['location']             = $('location').value;
801                 } else{
802                         data['location']             = '';
803                 }
804                 
805                 var tags = [];
806                 $$('.tags').each(function(element){
807                         var selected = element.readAttribute('data-selected');
808                         if(selected == "selected"){
809                                 var value = element.readAttribute('data-value');
810                                 tags.push(value);
811                         }
812                 });
813                 if (tags.length > 0){
814                         data['tag'] = tags;
815                 }else{
816                         data['tag'] = '';
817                 }
818                 
819                 var title = [];
820                 var shortdescription = [];
821                 var description = [];
822                 var dayofweek = [];
823                 var nottitle = [];
824                 var notshortdescription = [];
825                 var notdescription = [];
826                 var notdayofweek = [];
827                 $$('.filter').each(function(element){
828                         if (element.lastElementChild.className != 'add'){
829                                 var where = element.children[1].firstElementChild.value;
830                                 if (element.children[0].firstElementChild.value == 'include'){
831                                         if (where == 'title' ) title.push(element.children[2].firstElementChild.value);
832                                         if (where == 'shortdescription' ) shortdescription.push(element.children[2].firstElementChild.value);
833                                         if (where == 'description' ) description.push(element.children[2].firstElementChild.value);
834                                         if (where == 'dayofweek' ) dayofweek.push(element.children[2].lastElementChild.value);
835                                 } else{
836                                         if (where == 'title' ) nottitle.push(element.children[2].firstElementChild.value);
837                                         if (where == 'shortdescription' ) notshortdescription.push(element.children[2].firstElementChild.value);
838                                         if (where == 'description' ) notdescription.push(element.children[2].firstElementChild.value);
839                                         if (where == 'dayofweek' ) notdayofweek.push(element.children[2].lastElementChild.value);
840                                 }
841                         }
842                 });
843                 if (title.length > 0){
844                         data['title'] = title;
845                 }else{
846                         data['title'] = '';
847                 }
848                 if (shortdescription.length > 0){
849                         data['shortdescription'] = shortdescription;
850                 }else{
851                         data['shortdescription'] = '';
852                 }
853                 if (description.length > 0){
854                         data['description'] = description;
855                 }else{
856                         data['description'] = '';
857                 }
858                 if (dayofweek.length > 0){
859                         data['dayofweek'] = dayofweek;
860                 }else{
861                         data['dayofweek'] = '';
862                 }
863                 if (nottitle.length > 0){
864                         data['!title'] = nottitle;
865                 }else{
866                         data['!title'] = '';
867                 }
868                 if (notshortdescription.length > 0){
869                         data['!shortdescription'] = notshortdescription;
870                 }else{
871                         data['!shortdescription'] = '';
872                 }
873                 if (notdescription.length > 0){
874                         data['!description'] = notdescription;
875                 }else{
876                         data['!description'] = '';
877                 }
878                 if (notdayofweek.length > 0){
879                         data['!dayofweek'] = notdayofweek;
880                 }else{
881                         data['!dayofweek'] = '';
882                 }
883                 
884                 var bouquets = [];
885                 $$('.bouquet').each(function(element){
886                         if (element.lastElementChild.className != 'add'){
887                                 var select = element.children[0].firstElementChild;
888                                 bouquets.push( select.value );
889                         }
890                 });
891                 data['bouquets'] = bouquets.join(',');
892                 
893                 var services = [];
894                 $$('.service').each(function(element){
895                         if (element.lastElementChild.className != 'add'){
896                                 var select = element.children[1].firstElementChild;
897                                 services.push( select.value );
898                         }
899                 });
900                 data['services'] = services.join(',');
901                 
902                 if ($('vps_enabled').checked){
903                         data['vps_enabled'] = ($('vps_enabled').checked) ? '1' : '0';
904                         data['vps_overwrite'] = ($('vps_overwrite').checked) ? '1' : '0';
905                 } else{
906                         data['vps_enabled'] = '0';
907                         data['vps_overwrite'] = '0';
908                 }
909                 
910                 this.saveurl = [];
911                 for( key in data ){
912                         var value = data[key];
913                         if (typeof(value)=='string'){
914                                 this.saveurl.push( encodeURIComponent(key) + '=' + encodeURIComponent(data[key]) );
915                         } else if(typeof(value)=='object'&&(value instanceof Array)){
916                                 var len = value.length;
917                                 for (var i=0; i<len; i++){
918                                         this.saveurl.push( encodeURIComponent(key) + '=' + encodeURIComponent(value[i]) );
919                                 }
920                         }
921                 }
922                 this.saveurl = this.saveurl.join('&');
923                 //alert(this.saveurl);
924                 
925                 this.handler.save( this.saveurl, this.saveCallback.bind(this) );
926         },
927         saveCallback: function() {
928                 autotimereditorcore.list.reload();
929         },
930         
931         cancel: function() {
932                 this.reload();
933         },
934         
935         registerEvents: function(){
936                 $('justplay').on(
937                         'change',
938                         function(event, element){
939                                 this.onchangeSelect(element);
940                         }.bind(this)
941                 );
942                 $('timespan').on(
943                         'change',
944                         function(event, element){
945                                 this.onchangeCheckbox(element);
946                         }.bind(this)
947                 );
948                 $('timeframe').on(
949                         'change',
950                         function(event, element){
951                                 this.onchangeCheckbox(element);
952                         }.bind(this)
953                 );
954                 $('offset').on(
955                         'change',
956                         function(event, element){
957                                 this.onchangeCheckbox(element);
958                         }.bind(this)
959                 );
960                 $('maxdurationavailable').on(
961                         'change',
962                         function(event, element){
963                                 this.onchangeCheckbox(element);
964                         }.bind(this)
965                 );
966                 $('locationavailable').on(
967                         'change',
968                         function(event, element){
969                                 this.onchangeCheckbox(element);
970                         }.bind(this)
971                 );
972                 $('afterevent').on(
973                         'change',
974                         function(event, element){
975                                 this.onchangeSelectAfterEvent(element);
976                         }.bind(this)
977                 );
978                 $('aftereventusetimespan').on(
979                         'change',
980                         function(event, element){
981                                 this.onchangeCheckbox(element);
982                         }.bind(this)
983                 );
984                 $('counter').on(
985                         'change',
986                         function(event, element){
987                                 this.onchangeSelect(element);
988                         }.bind(this)
989                 );
990                 $('taglist').on(
991                         'click',
992                         function(event, element){
993                                 this.changeTag(element);
994                                 event.stop();
995                         }.bind(this)
996                 );
997                 $('usefilters').on(
998                         'change',
999                         function(event, element){
1000                                 this.onchangeCheckbox(element);
1001                         }.bind(this)
1002                 );
1003                 $('filterlist').on(
1004                         'change',
1005                         '.filterwhere', 
1006                         function(event, element){
1007                                 this.onchangeSelectFilter(element);
1008                         }.bind(this)
1009                 );
1010                 $('filterlist').on(
1011                         'click',
1012                         '.add', 
1013                         function(event, element){
1014                                 this.addFilter(element);
1015                         }.bind(this)
1016                 );
1017                 $('filterlist').on(
1018                         'click',
1019                         '.remove', 
1020                         function(event, element){
1021                                 this.removeFilter(element);
1022                         }.bind(this)
1023                 );
1024                 $('bouquetlist').on(
1025                         'click',
1026                         '.add', 
1027                         function(event, element){
1028                                 this.addBouquet(element);
1029                         }.bind(this)
1030                 );
1031                 $('bouquetlist').on(
1032                         'click',
1033                         '.remove', 
1034                         function(event, element){
1035                                 this.removeBouquet(element);
1036                         }.bind(this)
1037                 );
1038                 $('usebouquets').on(
1039                         'change',
1040                         function(event, element){
1041                                 this.onchangeCheckbox(element);
1042                         }.bind(this)
1043                 );
1044                 $('servicelist').on(
1045                         'click',
1046                         '.add', 
1047                         function(event, element){
1048                                 this.addService(element);
1049                         }.bind(this)
1050                 );
1051                 $('servicelist').on(
1052                         'click',
1053                         '.remove', 
1054                         function(event, element){
1055                                 this.removeService(element);
1056                         }.bind(this)
1057                 );
1058                 $('servicelist').on(
1059                         'change',
1060                         '.servicebouquet', 
1061                         function(event, element){
1062                                 this.onchangeSelectBouquet(element);
1063                         }.bind(this)
1064                 );
1065                 $('useservices').on(
1066                         'change',
1067                         function(event, element){
1068                                 this.onchangeCheckbox(element);
1069                         }.bind(this)
1070                 );
1071                 $('vps_enabled').on(
1072                         'change',
1073                         function(event, element){
1074                                 this.onchangeCheckbox(element);
1075                         }.bind(this)
1076                 );
1077                 $('save').on(
1078                         'click',
1079                         function(event, element){
1080                                 this.save();
1081                         }.bind(this)
1082                 );
1083                 $('cancel').on(
1084                         'click',
1085                         function(event, element){
1086                                 this.cancel();
1087                         }.bind(this)
1088                 );
1089         }
1090 });
1091
1092 var AutoTimerPreviewController = Class.create(Controller, {
1093         initialize: function($super, target){
1094                 $super(new AutoTimerPreviewHandler(target));
1095         },
1096         
1097         load: function(){
1098                 this.handler.load();
1099         },
1100         
1101         onFinished: function(){
1102                 $('list').selectedIndex=-1;
1103         },
1104         
1105         registerEvents: function(){
1106         }
1107 });
1108
1109 ///////////////////////////////////////////////////////////////////////////////
1110 // Handler
1111 var AutoTimerServiceListHandler = Class.create(AbstractContentHandler, {
1112         initialize: function($super){
1113                 $super(null, null);
1114                 this.provider = new SimpleServiceListProvider (this.onServicesReady.bind(this));
1115                 this.ajaxload = false;
1116         },
1117         
1118         load: function( ref, callback ){
1119                 this.callback = callback;
1120                 this.provider.load(ref);
1121         },
1122         
1123         onServicesReady: function(data){
1124                 var services = {};
1125                 var len = data.services.length;
1126                 for (var i=0; i<len; i++){
1127                         services[data.services[i].servicereference] = data.services[i].servicename;
1128                 }
1129                 if(typeof(this.callback) == "function"){
1130                         this.callback(services);
1131                 }
1132         }
1133 });
1134
1135 var AutoTimerSettingsHandler = Class.create(AbstractContentHandler, {
1136         initialize: function($super){
1137                 $super(null, null);
1138                 this.provider = new AutoTimerSettingsProvider(this.onSettingsReady.bind(this));
1139                 this.ajaxload = false;
1140         },
1141         
1142         load: function( callback ){
1143                 this.callback = callback;
1144                 this.provider.load();
1145         },
1146         
1147         onSettingsReady: function(data){
1148                 var settings = data;
1149                 if(typeof(this.callback) == "function"){
1150                         this.callback(settings);
1151                 }
1152         }
1153 });
1154
1155 var AutoTimerMenuHandler = Class.create(AbstractContentHandler,{
1156         initialize: function($super, target){
1157                 $super('tplAutoTimerMenu', target);
1158                 this.provider = new SimpleRequestProvider();
1159         },
1160         
1161         load: function(){
1162                 this.show({});
1163         },
1164         
1165         backup: function(parms, callback){
1166                 this.provider.simpleResultQuery(
1167                         URL.backup,
1168                         parms,
1169                         function(callback, transport){
1170                                 this.provider.simpleResultCallback(transport, this.backupCallback.bind(this, callback));
1171                         }.bind(this, callback));
1172         },
1173         backupCallback: function(callback, result){
1174                 var text = result.getStateText();
1175                 this.notify(text, result.getState());
1176                 if(typeof(callback) == "function"){
1177                         callback(text);
1178                 }
1179         },
1180
1181         restore: function(parms, callback){
1182                 this.provider.simpleResultQuery(
1183                         URL.restore,
1184                         parms,
1185                         function(callback, transport){
1186                                 this.provider.simpleResultCallback(transport, this.restoreCallback.bind(this, callback));
1187                         }.bind(this, callback));
1188         },
1189         restoreCallback: function(callback, result){
1190                 this.notify(result.getStateText(), result.getState());
1191                 if(typeof(callback) == "function"){
1192                         callback();
1193                 }
1194         },
1195 });
1196
1197 var AutoTimerListHandler  = Class.create(AbstractContentHandler, {
1198         initialize: function($super, target){
1199                 $super('tplAutoTimerList', target);
1200                 this.provider = new AutoTimerListProvider(this.show.bind(this));
1201                 this.ajaxload = true;
1202         },
1203         
1204         parse: function(parms, callback){
1205                 this.provider.simpleResultQuery(
1206                         URL.parse,
1207                         parms,
1208                         function(callback, transport){
1209                                 this.simpleResultCallback(transport, callback);
1210                                 if(typeof(callback) == "function"){
1211                                         callback();
1212                                 }
1213                         }.bind(this, callback));
1214         },
1215         
1216         add: function(parms, callback){
1217                 this.provider.simpleResultQuery(
1218                         URL.add, 
1219                         parms, 
1220                         function(callback, transport){
1221                                 this.simpleResultCallback(transport, callback);
1222                                 if(typeof(callback) == "function"){
1223                                         callback();
1224                                 }
1225                         }.bind(this, callback));
1226         },
1227         
1228         remove: function(parms, callback){
1229                 this.provider.simpleResultQuery(
1230                         URL.remove, 
1231                         parms, 
1232                         function(callback, transport){
1233                                 this.simpleResultCallback(transport, callback);
1234                                 if(typeof(callback) == "function"){
1235                                         callback();
1236                                 }
1237                         }.bind(this, callback));
1238         },
1239 });
1240
1241 var AutoTimerEditHandler = Class.create(AbstractContentHandler, {
1242         initialize: function($super, target){
1243                 $super('tplAutoTimerEdit', target);
1244                 this.provider = new AutoTimerEditProvider(this.show.bind(this));
1245                 this.ajaxload = true;
1246         },
1247         
1248         load: function( id ){
1249                 this.provider.load( id );
1250         },
1251         
1252         save: function(parms, callback){
1253                 this.provider.simpleResultQuery(
1254                         URL.edit, 
1255                         parms, 
1256                         function(callback, transport){
1257                                 this.simpleResultCallback(transport, callback);
1258                                 if(typeof(callback) == "function"){
1259                                         callback();
1260                                 }
1261                         }.bind(this, callback));
1262         },
1263 });
1264
1265 var AutoTimerPreviewHandler = Class.create(AbstractContentHandler, {
1266         initialize: function($super, target){
1267                 $super('tplAutoTimerPreview', target);
1268                 this.provider = new AutoTimerPreviewProvider(this.show.bind(this));
1269                 this.ajaxload = true;
1270         },
1271         
1272         load: function(){
1273                 this.provider.load();
1274         },
1275 });
1276
1277 ///////////////////////////////////////////////////////////////////////////////
1278 // Provider
1279 var AutoTimerSettingsProvider = Class.create(AbstractContentProvider, {
1280         initialize: function($super, showFnc){
1281                 $super(URL.get, showFnc);
1282         },
1283         
1284         load: function( ){
1285                 this.getUrl(this.url, null, this.loadCallback.bind(this), this.errorback.bind(this));
1286         },
1287         
1288         loadCallback: function(transport){
1289                 var data = this.renderXML(this.getXML(transport));
1290                 this.show(data);
1291         },
1292         
1293         renderXML: function(xml){
1294                 this.settings = new AutoTimerSettings(xml).toJSON();
1295                 return this.settings;
1296         },
1297 });
1298
1299 var AutoTimerListProvider = Class.create(AbstractContentProvider, {
1300         initialize: function($super, showFnc){
1301                 $super(URL.list, showFnc);
1302         },
1303         
1304         renderXML: function(xml){
1305                 this.list = new AutoTimerList(xml).getList();
1306                 return {list : this.list};
1307         },
1308         
1309         getAutoTimer: function(id){
1310                 var autotimer = null;
1311                 for (idx in this.list) {
1312                         if (this.list[idx].id == id){
1313                                 autotimer = this.list[idx];
1314                                 break;
1315                         }
1316                 }
1317                 return autotimer;
1318         },
1319         
1320         getAutoTimerIndex: function(id){
1321                 var idx = null;
1322                 for (i in this.list) {
1323                         if (this.list[i].id == id){
1324                                 idx = i;
1325                                 break;
1326                         }
1327                 }
1328                 return idx;
1329         }
1330 });
1331
1332 var AutoTimerEditProvider = Class.create(AbstractContentProvider, {
1333         initialize: function($super, showFnc){
1334                 $super(URL.list, showFnc);
1335         },
1336         
1337         load: function( id ){
1338                 callback = this.callback.bind(this, id);
1339                 this.getUrl(this.url, null, callback, this.errorback.bind(this));
1340         },
1341         
1342         callback: function(id, transport){
1343                 var data = this.renderXML(this.getXML(transport), id);
1344                 this.show(data);
1345         },
1346         
1347         renderXML: function(xml, id){
1348                 this.edit = new AutoTimerEdit(xml, id).getItem();
1349                 return this.edit;
1350         },
1351 });
1352
1353 var AutoTimerPreviewProvider = Class.create(AbstractContentProvider, {
1354         initialize: function($super, showFnc){
1355                 $super(URL.preview, showFnc);
1356         },
1357         
1358         callback: function(transport){
1359                 var data = this.renderXML(this.getXML(transport));
1360                 this.show(data);
1361         },
1362         
1363         renderXML: function(xml){
1364                 this.list = new AutoTimerPreview(xml).getList();
1365                 return {list : this.list};
1366         },
1367 });
1368
1369 ///////////////////////////////////////////////////////////////////////////////
1370 // Objects
1371 function AutoTimerSettings(xml){
1372         this.xmlitems = getNamedChildren(xml, "e2settings", "e2setting");
1373         this.json = new Array();
1374         var len = this.xmlitems.length;
1375         for (var i=0; i<len; i++){
1376                 var element = this.xmlitems[i].getElementsByTagName('e2settingname');
1377                 var name = element[0].firstChild.nodeValue;
1378                 var element = this.xmlitems[i].getElementsByTagName('e2settingvalue');
1379                 var value = element[0].firstChild.nodeValue;
1380                 this.json[name] = value;
1381         }
1382         this.toJSON = function(){
1383                 return this.json;
1384         };
1385 }
1386
1387 function AutoTimerPreview(xml){
1388         this.xmlitems = getNamedChildren(xml, "e2autotimersimulate", "e2simulatedtimer");
1389         this.list = [];
1390         this.getList = function(){
1391                 if(this.list.length === 0){
1392                         var len = this.xmlitems.length;
1393                         for (var i=0; i<len; i++){
1394                                 var xmlitem = this.xmlitems[i];
1395                                 var timer = {
1396                                         'name' :           getNodeContent(xmlitem, 'e2name'),
1397                                         'begin' :          toReadableDateTime( new Date( getNodeContent(xmlitem, 'e2timebegin') * 1000 ) ),
1398                                         'end' :            toReadableDateTime( new Date( getNodeContent(xmlitem, 'e2timeend') * 1000 ) ),
1399                                         'servicename' :    getNodeContent(xmlitem, 'e2servicename'),
1400                                         'autotimer' :      getNodeContent(xmlitem, 'e2autotimername'),
1401                                 };
1402                                 this.list.push(timer);
1403                         }
1404                         this.list.sort(sortAutoTimer);
1405                         return this.list;
1406                 }
1407         };
1408 }
1409
1410 function AutoTimerList(xml){
1411         this.xmlitems = getNamedChildren(xml, "autotimer", "timer");
1412         this.list = [];
1413         this.getList = function(){
1414                 if(this.list.length === 0){
1415                         var len = this.xmlitems.length;
1416                         for (var i=0; i<len; i++){
1417                                 var autotimer = new AutoTimerListEntry(this.xmlitems.item(i)).toJSON();
1418                                 this.list.push(autotimer);
1419                         }
1420                 }
1421                 this.list.sort(sortAutoTimer);
1422                 return this.list;
1423         };
1424 }
1425
1426 function AutoTimerListEntry(xml){
1427         // Extract only list relevant parts
1428         this.id = xml.getAttribute('id');
1429         this.enabled = xml.getAttribute('enabled');
1430         this.css = (this.enabled == 'yes') ? 'enabled' : 'disabled';
1431         this.name = xml.getAttribute('name');
1432         if ( (this.name == undefined) || (this.name == '') ){
1433                 this.name = xml.getAttribute('match');
1434         }
1435         this.json = {
1436                 'id' :                this.id,
1437                 'enabled' :           this.enabled,
1438                 'css' :               this.css,
1439                 'name' :              this.name,
1440         };
1441         this.toJSON = function(){
1442                 return this.json;
1443         };
1444 }
1445
1446 function AutoTimerEdit(xml, id){
1447         this.xmldefaults = getNamedChildren(xml, "autotimer", "defaults");
1448         this.defaults = AutoTimerDefaults(this.xmldefaults.item(0));
1449         this.xmlitems = getNamedChildren(xml, "autotimer", "timer");
1450         this.autotimer = null;
1451         this.getItem = function(){
1452                 var len = this.xmlitems.length;
1453                 for (var i=0; i<len; i++){
1454                         if (this.xmlitems.item(i).getAttribute('id') == id){
1455                                 this.autotimer = new AutoTimer(this.xmlitems.item(i), this.defaults).toJSON();
1456                                 break;
1457                         }
1458                 }
1459                 return this.autotimer;
1460         };
1461 }
1462
1463 function AutoTimerDefaults(xml){        
1464         this.defaults = {}
1465         // Extract default values
1466         for (var i=0;i<xml.attributes.length;i++){
1467                 this.defaults[xml.attributes[i].name] = xml.attributes[i].value;
1468         }
1469         return this.defaults;
1470 }
1471
1472 function AutoTimer(xml, defaults){      
1473         // Items that must exist
1474         this.id = xml.getAttribute('id');
1475         this.enabled = (xml.getAttribute('enabled')=='yes') ? 'checked' : '';
1476         
1477         var name = xml.getAttribute('name');
1478         this.match = xml.getAttribute('match');
1479         this.name = (this.name == undefined) ? name : this.match;
1480         
1481         var encoding = getAttribute(xml, 'encoding', defaults);
1482         if (encoding==undefined) encoding = 'ISO8859-15';
1483         var options = ['ISO8859-15', 'UTF-8'];
1484         this.encoding = toOptionList(options, encoding);
1485         this.encoding.shift();
1486
1487         // Items which only exists if they differ from the default value
1488         var searchType = getAttribute(xml, 'searchType', defaults);
1489         if (searchType==undefined) searchType = 'partial';
1490         var options = {};
1491         options['partial'] = 'partial match';
1492         options['exact'] = 'exact match';
1493         options['description'] = 'description match';
1494         this.searchType = createOptionList(options, searchType);
1495
1496         var searchCase = getAttribute(xml, 'searchCase', defaults);
1497         if (searchCase==undefined) searchCase = 'insensitive';
1498         var options = {};
1499         options['sensitive'] = 'case-sensitive search';
1500         options['insensitive'] = 'case-insensitive search';
1501         this.searchCase = createOptionList(options, searchCase);
1502
1503         var justplay = getAttribute(xml, 'justplay', defaults);
1504         if (justplay==undefined) justplay = 'record';
1505         var options = {};
1506         options['0'] = 'record';
1507         options['1'] = 'zap';
1508         this.justplay = createOptionList(options, justplay);
1509         
1510         var setEndtime = getAttribute(xml, 'setEndtime', defaults);
1511         if (setEndtime==undefined || setEndtime=='1'){
1512                 setEndtime = 'checked';
1513         }else{
1514                 setEndtime = '';
1515         }
1516         this.setEndtime = setEndtime;
1517         
1518         this.overrideAlternatives = (getAttribute(xml, 'overrideAlternatives', defaults)) ? 'checked' : '';
1519         
1520         var from = getAttribute(xml, 'from', defaults);
1521         var to = getAttribute(xml, 'to', defaults);
1522         var usetimespan = (from || to) ? 'checked' : '';
1523         if (to == undefined) to = '23:15';
1524         if (from == undefined) from = '20:15';
1525         this.timespan = {
1526                 'usetimespan' : usetimespan,
1527                 'from' : from,
1528                 'to' : to,
1529         }       
1530         
1531         var after = getAttribute(xml, 'after', defaults);
1532         var before = getAttribute(xml, 'before', defaults);
1533         var usetimeframe = (before || after) ? 'checked' : '';
1534         if (after == undefined) {
1535                 after = new Date();
1536                 after = new Date( after.getUTCFullYear(), after.getUTCMonth(), after.getUTCDate() + 7 );
1537         } else {
1538                 after = new Date( after * 1000 )
1539         }
1540         if (this.before == undefined) {
1541                 before = new Date();
1542         } else {
1543                 before = new Date( this.before * 1000 )
1544         }
1545         this.timeframe = {
1546                 'usetimeframe' : usetimeframe,
1547                 'after' : toReadableDate( after ),
1548                 'before' : toReadableDate( before ),
1549         }       
1550         
1551         var offset = getAttribute(xml, 'offset', defaults);
1552         var useoffset = (offset) ? 'checked' : '';
1553         if (offset != undefined) {
1554                 offset = offset.split(',');
1555                 if (offset.length!=2){
1556                         offset = [offset, offset];
1557                 }
1558         } else {
1559                 offset = ['5','5'];
1560         }
1561         var begin = parseInt(offset[0]);
1562         var end = parseInt(offset[1]);
1563         this.offset = {
1564                 'useoffset' : useoffset,
1565                 'begin' : numericalOptionList(0, 100, begin),
1566                 'end' : numericalOptionList(0, 100, end),
1567         }       
1568         
1569         var maxduration = getAttribute(xml, 'maxduration', defaults);
1570         var usemaxduration = (maxduration) ? 'checked' : '';
1571         if (maxduration == undefined) maxduration = 70;
1572         this.maxduration = {
1573                 'usemaxduration' : usemaxduration,
1574                 'maxduration' : numericalOptionList(0, 999, maxduration),
1575         }       
1576         
1577         var xmlafterevents = xml.getElementsByTagName('afterevent');
1578         var afterevent = '';
1579         var aftereventFrom = '';
1580         var aftereventTo = '';
1581         if (xmlafterevents.length > 0){
1582                 var xmlafterevent = xmlafterevents.item(0);
1583                 afterevent = xmlafterevent.firstChild.nodeValue;
1584                 aftereventFrom = xmlafterevent.getAttribute('from');
1585                 aftereventTo = xmlafterevent.getAttribute('to');
1586         }
1587         var useaftereventtimespan = (aftereventFrom || aftereventTo) ? 'checked' : '';
1588         if (aftereventFrom == undefined || aftereventFrom == '') aftereventFrom = '23:15';
1589         if (aftereventTo == undefined || aftereventTo =='') aftereventTo = '07:00';
1590         if (afterevent == '') afterevent = 'default';
1591         //TODO AutoTimer is a bit inconsistent: sometimes it is none or nothing
1592         if (afterevent == 'shutdown') afterevent = 'deepstandby';
1593         if (afterevent == 'none') afterevent = 'nothing';
1594         //ENDTODO
1595         var options = {};
1596         options['default'] = 'Standard';
1597         options['nothing'] = 'Do nothing';
1598         options['standby'] = 'Go to Standby';
1599         options['deepstandby'] = 'Go to Deep Standby';
1600         options['auto'] = 'auto';
1601         this.afterevent = {
1602                 'options' : createOptionList(options, afterevent),
1603                 'usetimespan' : useaftereventtimespan,
1604                 'from' : aftereventFrom,
1605                 'to' : aftereventTo,
1606         }
1607         
1608         //TODO TEST lastactivation lastbegin
1609         var counter = getAttribute(xml, 'counter', defaults);
1610         var left = getAttribute(xml, 'left', defaults);
1611         var counterFormat = getAttribute(xml, 'counterFormat', defaults);
1612         var lastActivation = getAttribute(xml, 'lastActivation', defaults);
1613         var lastBegin = getAttribute(xml, 'lastBegin', defaults);
1614         if (counter==undefined) counter = 0;
1615         if (left == undefined) left = 0;
1616         if (counterFormat==undefined) counterFormat = '';
1617         var counterFormatOptions = {};
1618         counterFormatOptions[''] = 'Never';
1619         counterFormatOptions['%m'] = 'Monthly';
1620         counterFormatOptions['%U'] = 'Weekly (Sunday)';
1621         counterFormatOptions['%W'] = 'Weekly (Monday)';
1622         if (lastActivation == undefined  || lastActivation == '') {
1623                 lastActivation = '';
1624         }else if (lastActivation == '0') {
1625                 lastBegin = '0';
1626         } else{
1627                 lastActivation = toReadableDate(lastActivation);
1628         }
1629         if (lastBegin == undefined || lastBegin == '') {
1630                 lastBegin = '';
1631         }else if (lastBegin == '0') {
1632                 lastBegin = '0';
1633         } else{
1634                 lastBegin = toReadableDate(lastBegin);
1635         }
1636         this.counter = {
1637                 'options' : numericalOptionList(0, 100, counter),
1638                 'left' : numericalOptionList(0, 100, left),
1639                 'counterFormat' : createOptionList(counterFormatOptions, counterFormat),
1640                 'lastActivation' : lastActivation,
1641                 'lastBegin' : lastBegin,
1642         }
1643
1644         avoidDuplicateDescription = getAttribute(xml, 'avoidDuplicateDescription', defaults);
1645         if (avoidDuplicateDescription==undefined) avoidDuplicateDescription = '0';
1646         var options = {};
1647         options['0'] = 'No';
1648         options['1'] = 'On same service';
1649         options['2'] = 'On any service';
1650         options['3'] = 'Any service/recording';
1651         this.avoidDuplicateDescription = createOptionList(options, avoidDuplicateDescription);
1652
1653         var location = getAttribute(xml, 'location', defaults);
1654         var uselocation = (location) ? 'checked' : '';
1655         if (location == undefined) {
1656                 location = '';
1657         }
1658         var l = toOptionList(autotimereditorcore.locations, this.location);
1659         l.shift();
1660         this.location = {
1661                 'uselocation' : uselocation,
1662                 'locations' : l,
1663         }
1664         
1665         var xmltags = xml.getElementsByTagName('e2tags');
1666         var tags = '';
1667         if (xmltags.length > 0){
1668                 tags = xmltags.item(0).firstChild.nodeValue;
1669         }
1670         this.tags = toOptionList(autotimereditorcore.tags, tags, " ");
1671         this.tags.shift();
1672         
1673         var filters = [];
1674         var filtertags = ['include', 'exclude'];
1675         var tlen = filtertags.length;
1676         for (var t=0; t<tlen; t++){
1677                 var xmlfilters = xml.getElementsByTagName(filtertags[t]);
1678                 var len = xmlfilters.length;
1679                 for (var i=0; i<len; i++){
1680                         var text = xmlfilters.item(i).firstChild.nodeValue;
1681                         var weekday = text;
1682                         if (text in weekdays ){
1683                                 text = '';
1684                         } else{
1685                                 weekday = '0';
1686                         }
1687                         
1688                         filters.push({ 
1689                                 'type' : createOptionList(types, xmlfilters.item(i).nodeName),
1690                                 'where' : createOptionList(wheres, xmlfilters.item(i).getAttribute('where')),
1691                                 'text' : text,
1692                                 'weekdays' : createOptionList(weekdays, weekday),
1693                                 'class' : 'remove',
1694                         });
1695                 }
1696         }
1697         var usefilters = (filters.length > 0) ? 'checked' : '';
1698         filters.push({ 
1699                 'type' : createOptionList(types, 'include'),
1700                 'where' : createOptionList(wheres, 'title'),
1701                 'text' : '',
1702                 'weekdays' : createOptionList(weekdays, '0'),
1703                 'class' : 'add',
1704         });
1705         this.filters = {
1706                 'usefilters' : usefilters,
1707                 'filters' : filters,
1708         }
1709         
1710         var bouquetoptions = createOptionList(autotimereditorcore.bouquets);
1711         var bouquets = [];
1712         var services = [];
1713         var xmlservices = xml.getElementsByTagName('e2service');
1714         var len = xmlservices.length;
1715         for (var i=0; i<len; i++){
1716                 var name = xmlservices.item(i).getElementsByTagName('e2servicename');
1717                 if(name.item(0).firstChild == null){
1718                         name = '';
1719                 }
1720                 else{
1721                         name = name.item(0).firstChild.nodeValue;
1722                 }
1723                 var reference = xmlservices.item(i).getElementsByTagName('e2servicereference');
1724                 reference = escape(reference.item(0).firstChild.nodeValue);
1725                 // Check if service is a bouquet
1726                 // Service reference flags == isDirectory | mustDescent | canDescent (== 7)
1727                 if (unescape(reference).slice(2,3) == "7"){
1728                         bouquets.push({
1729                                 'bouquet' : createOptionList(autotimereditorcore.bouquets, reference),
1730                                 'class' : 'remove',
1731                         });
1732                 }else{
1733                         var service = [];
1734                         var bouquet = bouquetoptions.slice(0);
1735                         service.push({
1736                                         'value' : reference,
1737                                         'txt' : name,
1738                                         'selected' : 'selected'
1739                                 });
1740                         bouquet.push({
1741                                         'value' : '',
1742                                         'txt' : '---',
1743                                         'selected' : 'selected'
1744                                 });
1745                         services.push({ 
1746                                 'bouquet' : bouquet,
1747                                 'service' : service,
1748                                 'class' : 'remove',
1749                         });
1750                 }
1751         }
1752         
1753         var usebouquets = (bouquets.length > 0) ? 'checked' : '';
1754         bouquets.push({ 
1755                 'bouquet' : bouquetoptions,
1756                 'class' : 'add',
1757         });
1758         this.bouquets = {
1759                 'usebouquets' : usebouquets,
1760                 'bouquets' : bouquets,
1761         }
1762         
1763         var useservices = (services.length > 0) ? 'checked' : '';
1764         services.push({ 
1765                 'bouquet' : bouquetoptions,
1766                 'service' : bouquetoptions,
1767                 'class' : 'add',
1768         });
1769         this.services = {
1770                 'useservices' : useservices,
1771                 'services' : services,
1772         }
1773         
1774         var hasVps = (autotimereditorcore.hasVps == "True") ? '' : 'invisible';
1775         var vps_enabled = (getAttribute(xml, 'vps_enabled', defaults)) ? 'checked' : '';
1776         var vps_overwrite = (getAttribute(xml, 'vps_overwrite', defaults)) ? 'checked' : '';
1777         this.vps = {
1778                 'hasVPS' : hasVps,
1779                 'vps_enabled' : vps_enabled,
1780                 'vps_overwrite' : vps_overwrite,
1781         }
1782         
1783         this.json = {   
1784                         'id' :                    this.id,
1785                         'enabled' :               this.enabled,
1786                         'name' :                  this.name,
1787                         'match' :                 this.match,
1788                         'encoding' :              this.encoding,
1789                         
1790                         'searchType' :            this.searchType,
1791                         'searchCase' :            this.searchCase,
1792                         
1793                         'justplay' :              this.justplay,
1794                         'setEndtime' :            this.setEndtime,
1795                         
1796                         'overrideAlternatives' :  this.overrideAlternatives,
1797                         'timespan' :              this.timespan,
1798                         'timeframe' :             this.timeframe,
1799                         'offset' :                this.offset,
1800                         'maxduration' :           this.maxduration,
1801                                                 
1802                         'afterevent' :            this.afterevent,
1803                         'counter' :               this.counter,
1804                         
1805                         'avoidDuplicateDescription' :  this.avoidDuplicateDescription,
1806                         'location' :                   this.location,
1807                         'tags' :                       this.tags,
1808                         'filters' :                    this.filters,
1809                         'bouquets' :                   this.bouquets,
1810                         'services' :                   this.services,
1811                         
1812                         'vps' :                   this.vps,
1813         };
1814
1815         this.toJSON = function(){
1816                 return this.json;
1817         };
1818 }