FW_version["fhemweb_weekprofile.js"] = "$Id$"; var language = 'de'; //for tooltip $(document).ready(function(){ $('[data-toggle="tooltip"]').tooltip(); language = window.navigator.userLanguage || window.navigator.language; }); var shortDays = ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]; function FW_weekprofileInputDialog(title,inp,def,parent,callback) { var div = $("
"); var table = $(""); var content = []; for(var i=0; i').get(0); if (def) content[i].value = def[i]; var tr = $(""); var td1 = $("'; table += ''; } } table += "
"); $(td1).append(title[i]); if (inp[i] == 'hidden') { $(td1).attr("colspan","2"); $(td1).attr("align","center"); } var td2 = $(""); $(td2).append(content[i]); $(tr).append(td1); $(tr).append(td2); table.append(tr); } $(div).append(table); $("body").append(div); $(div).dialog({ dialogClass:"no-close",modal:true, width:"auto", closeOnEscape:true, maxWidth:$(window).width()*0.9, maxHeight:$(window).height()*0.9, title: title, buttons: [{text:"OK", click:function(){ $(this).dialog("close"); $(div).remove(); if(callback) { var backCont = []; for(var i=0; i=0) sel=1; table += '
"; var div = $("
"); $(div).append(title); $(div).append(table); if (freeInp && freeInp == 1) $(div).append(''); $("body").append(div); $(div).dialog({ dialogClass:"no-close",modal:true, width:"auto", closeOnEscape:true, maxWidth:$(window).width()*0.9, maxHeight:$(window).height()*0.9, title: title, buttons: [{text:"OK", click:function(){ var res=[]; if($("#FW_weekprofileMultiSelDiologFreeText").val()) res.push($("#FW_weekprofileMultiSelDiologFreeText").val()); $("#FW_weekprofileMultiSelDiolog table input").each(function(){ if($(this).prop("checked")) res.push($(this).attr("name")); }); $(this).dialog("close"); $(div).remove(); if(callback) callback(res); }},{text:"CANCEL", click:function(){ $(this).dialog("close"); $(div).remove(); if(callback) callback(null); }}] }); if(parent) $(div).dialog( "option", "position", { my: "left top", at: "right bottom", of: parent, collision: "flipfit" }); } function FW_GetTranslation(widget,translate) { if (widget.TRANSLATIONS == null) return translate; var translated = widget.TRANSLATIONS[translate]; if (translated.length == 0) return translate; return translated; } function weekprofile_DoEditWeek(devName,newPage) { var widget = $('div[informid="'+devName+'"]').get(0); if (newPage == 1) { var csrfToken = $("body").attr('fwcsrf'); var url = FW_root+'?cmd={weekprofile_editOnNewpage("'+widget.DEVICE+'","'+widget.CURTOPIC+':'+widget.CURPRF+'");;}'; if (csrfToken) url = url + '&fwcsrf='+ csrfToken; window.location.assign(url); } else { widget.MODE = 'EDIT'; $(widget.MENU.BASE).hide(); widget.setValueFn("REUSEPRF"); } } function FW_weekprofilePRF_chached(devName,select) { var widget = $('div[informid="'+devName+'"]').get(0) var prfName = select.options[select.selectedIndex].value; widget.CURPRF = prfName; widget.PROFILE = null; FW_queryValue('get '+devName+' profile_data '+widget.CURTOPIC+':'+widget.CURPRF+' 1', widget); } function FW_weekprofileTOPIC_chached(devName,select) { var widget = $('div[informid="'+devName+'"]').get(0) var topicName = select.options[select.selectedIndex].value; widget.CURTOPIC = topicName; widget.CURPRF = null; widget.PROFILE = null; FW_cmd(FW_root+'?cmd=get '+devName+' profile_names '+widget.CURTOPIC+'&XHR=1',function(data){FW_weekprofileGetValues(devName,"PROFILENAMES",data);}); } function FW_weekprofileChacheTo(devName,topicName,profileName) { var widget = $('div[informid="'+devName+'"]').get(0) widget.CURTOPIC = topicName; widget.CURPRF = profileName; widget.PROFILE = null; FW_cmd(FW_root+'?cmd=get '+devName+' profile_names '+widget.CURTOPIC+'&XHR=1',function(data){FW_weekprofileGetValues(devName,"PROFILENAMES",data);}); } function FW_weekprofileRestoreTopic(devName,bnt) { var widget = $('div[informid="'+devName+'"]').get(0) FW_weekprofileInputDialog(["

Restore topic: '"+widget.CURTOPIC+"' ?

"],["hidden"],null,bnt,function(name,ok){ if (ok == 1) FW_cmd(FW_root+'?cmd=set '+devName+' restore_topic '+widget.CURTOPIC+'&XHR=1',function(data){ if (data != "") { console.log(devName+" error restore topic '" +data+"'"); FW_errmsg(devName+" error restore topic '" +data+"'",5000); return; } }); }); } function FW_weekprofileSendToDev(devName,bnt) { var widget = $('div[informid="'+devName+'"]').get(0) var deviceLst = null; bnt.setValueFn = function(data) { try { deviceLst=JSON.parse(data); var devicesNames = []; var devicesAlias = []; for (var k=0; k < deviceLst.length; k++) { devicesNames.push(deviceLst[k]['NAME']); devicesAlias.push(deviceLst[k]['ALIAS']); } var selected = []; if (widget.MASTERDEV) selected.push(widget.MASTERDEV); FW_weekprofileMultiSelDialog("Device(s):",devicesNames,devicesAlias,selected,1,bnt, function(sndDevs) { if (!sndDevs || sndDevs.length==0) return; FW_cmd(FW_root+"?cmd=set "+widget.DEVICE+" send_to_device "+widget.CURTOPIC+':'+widget.CURPRF+" "+sndDevs.join(',')+"&XHR=1",function(arg) {FW_weekprofileSendCallback(widget.DEVICE,arg);}); }); } catch(e){ console.log(devName+" error parsing json '" +data+"'"); FW_errmsg(devName+" Parameter "+e,5000); return; } } FW_queryValue('get '+devName+' sndDevList', bnt); } function FW_weekprofileCopyPrf(devName,lnk) { var widget = $('div[informid="'+devName+'"]').get(0) var title = []; var inp = []; var def = []; var idx = 0; var topic = ''; if (widget.USETOPICS==1) { topic=widget.CURTOPIC+":"; } title[idx] = "

Create new entry from: "+topic+widget.CURPRF+"

"; inp[idx] = "hidden"; def[idx] = ''; idx++; if (widget.USETOPICS==1) { title[idx] = "

Reference:

"; inp[idx] = "checkbox"; def[idx] = ''; idx++; title[idx] = "

Topic:

"; inp[idx] = "text"; def[idx] = widget.CURTOPIC; idx++; } title[idx] = "

Name:

"; inp[idx] = "text"; def[idx] = ''; FW_weekprofileInputDialog(title,inp,def,lnk,function(names,ok){ if (ok < 1) return; var topic = widget.CURTOPIC; var name = names[names.length-1].trim(); var ref = 0; if (widget.USETOPICS==1) { topic = names[names.length-2].trim(); ref = names[names.length-3]; } if (topic.length < 1 || name.length < 1) return; if (ref != 0) FW_cmd(FW_root+"?cmd=set "+widget.DEVICE+" reference_profile "+widget.CURTOPIC+':'+widget.CURPRF+" "+topic+':'+name+"&XHR=1",function(arg) {FW_weekprofileSendCallback(widget.DEVICE,arg);}); else FW_cmd(FW_root+"?cmd=set "+widget.DEVICE+" copy_profile "+widget.CURTOPIC+':'+widget.CURPRF+" "+topic+':'+name+"&XHR=1",function(arg) {FW_weekprofileSendCallback(widget.DEVICE,arg);}); }); } function FW_weekprofileRemovePrf(devName,lnk) { var widget = $('div[informid="'+devName+'"]').get(0) FW_weekprofileInputDialog(["

Delete Profile: '"+widget.CURTOPIC+':'+widget.CURPRF+"' ?

"],["hidden"],null,lnk,function(name,ok){ if (ok < 1) return; FW_cmd(FW_root+"?cmd=set "+widget.DEVICE+" remove_profile "+widget.CURTOPIC+':'+widget.CURPRF+"&XHR=1",function(arg) {FW_weekprofileSendCallback(widget.DEVICE,arg);}); }); } function FW_weekprofileShow(widget) { $(widget.MENU.BASE).show(); var editIcon = $(widget.MENU.BASE).find('a[name="'+widget.DEVICE+'.edit"]').get(0); $(editIcon).css("visibility", "visible"); //hide() remove the element $(widget.MENU.CONTENT).empty(); var selMargin=0; var tdStyle="style=\"padding-left:0px;padding-right:0px\""; if (widget.USETOPICS == 1) { selMargin = 2; tdStyle = "style=\"padding:0px\""; } if (widget.PROFILENAMES) { var html=''; html += ''; html += ""; html += ""; html += ""; if (widget.PRFREF) { $(editIcon).css("visibility", "hidden"); var names = widget.PRFREF.split(':'); names[0] = names[0].trim(); names[1] = names[1].trim(); html += ""; } html += "
"; if (widget.USETOPICS == 1 && widget.TOPICNAMES) { html += ""; } html += ""; html += ""; html += " " html += ""; html += " " if (widget.USETOPICS == 0) { html += ""; } else { html += ""; } html += "
"; html += ""; html += "
"; html += " " html += "REF: "+names[0]+":"+names[1]+""; html += "
"; $(widget.MENU.CONTENT).append(html); var select = $(widget.MENU.CONTENT).find('select[name="PROFILES"]').get(0); var prfName = select.options[select.selectedIndex].value; if (widget.CURPRF != prfName) FW_weekprofilePRF_chached(widget.DEVICE,select); } if (!widget.PROFILE) { return; } var table = widget.CONTENT; $(table).empty(); for (var i = 0; i < shortDays.length; ++i) { $(table).append(''+widget.WEEKDAYS[i]+''); var tr = $(table).find("tr").get(i); for (var k = 0; k < widget.PROFILE[shortDays[i]]['temp'].length; ++k) { var str = ''; k>0 ? str = widget.PROFILE[shortDays[i]]['time'][k-1] : str = '00:00'; str = str + '-' + widget.PROFILE[shortDays[i]]['time'][k]; $(tr).append(''+str+ ''); str = widget.PROFILE[shortDays[i]]['temp'][k]; var tempV = parseFloat(str); if(!isNaN(tempV)) { str += ' °C'; } $(tr).append(''+str+ ''); } } } function FW_weekprofileEditTime_changed(inp) { if (inp == null) {return;} var times = inp.value.split(':'); if (times.length == 0) return; var hour = parseInt(times[0]); var min = (times.length==2) ? parseInt(times[1]): 0; inp.value = ((hour<10)?("0"+hour):hour) +":"+ ((min<10)?("0"+min):min); //set new end time as new start time for the next interval var nexttr = inp.parentNode.parentNode.nextSibling; if (nexttr!=null){ nexttr.firstChild.firstChild.innerHTML=inp.value; } } function FW_weekprofileEditRowStyle(table) { var alltr = $(table).find("tr"); for (var i = 0; i < alltr.length; ++i){ var delButton = $(alltr[i]).find('input[name="DEL"]'); var addButton = $(alltr[i]).find('input[name="ADD"]'); var inp = $(alltr[i]).find('input[name="ENDTIME"]'); $(alltr[i]).attr('class',(i%2==0)? "odd":"even"); delButton.attr('type',"button"); addButton.attr('type',"button"); inp.removeAttr('style'); inp.removeAttr('readonly'); FW_weekprofileEditTime_changed(inp.get(0)); if (i==0){ $(alltr[i]).find('span[name="STARTTIME"]').get(0).innerHTML = "00:00"; if (alltr.length == 1){ delButton.attr('type',"hidden"); } } if (i==alltr.length-1){ if (alltr.length > 1){ addButton.attr('type',"hidden"); } inp.attr('style',"border:none;background:transparent;box-shadow:none"); inp.get(0).value = "24:00"; inp.attr('readonly',true); } } } function FW_weekprofileEditAddInterval(tr) { var newtr = $(tr).clone(true); var alltr = $(tr).parent().children(); for (var i = 0; i < alltr.length; ++i) { if ( $(alltr[i]).is($(tr))) { newtr.insertAfter($(alltr[i])); break; } } FW_weekprofileEditRowStyle($(tr).parent()); var timSel = newtr.find('input[name="ENDTIME"]'); if (alltr.length == 1) timSel = $(tr).find('input[name="ENDTIME"]'); timSel.focus(); timSel.select(); } function FW_weekprofileEditDelInterval(tr) { var parent = $(tr).parent(); $(tr).remove(); FW_weekprofileEditRowStyle(parent) } function FW_weekprofileTransDay(devName,day,bnt) { var widget = $('div[informid="'+devName+'"]').get(0); var srcDay = $(widget.CONTENT).find("table[id*=\"weekprofile."+widget.DEVICE+"\"][data-day*=\""+shortDays[day]+"\"]"); var dayNames = []; var dayAlias = []; for (var k=0; k < shortDays.length; k++) { if (k != day) { dayNames.push(shortDays[k]); dayAlias.push(widget.WEEKDAYS[k]); } } var selected = []; FW_weekprofileMultiSelDialog("Days(s):",dayNames,dayAlias,selected,0,bnt, function(selDays) { if (!selDays || selDays.length==0) return; for (var k=0; k < selDays.length; k++) { var destDay = $(widget.CONTENT).find("table[id*=\"weekprofile."+widget.DEVICE+"\"][data-day*=\""+selDays[k]+"\"]"); destDay.empty(); destDay.append(srcDay.clone().contents()); } }); } function FW_weekprofileTemp_chached(select) { var val = select.options[select.selectedIndex].value; $(select).find("option").removeAttr('selected'); $(select).val(val); $(select.options[select.selectedIndex]).attr("selected","selected"); } function FW_weekprofileEditDay(widget,day) { if (widget.PROFILE == null) { return ""; } var div = $("
").get(0); var html= ''; html += "
"; html += ""+widget.WEEKDAYS[day]+""; html += "-->"; html += "
"; $(div).append(html); var table = $("").get(0); $(table).attr('id',"weekprofile."+widget.DEVICE).attr("data-day", shortDays[day]); $(table).attr('class',"block wide weekprofile"); html = ''; var sday = shortDays[day]; var times = widget.PROFILE[sday]['time']; var temps = widget.PROFILE[sday]['temp']; for (var i = 0; i < times.length; ++i) { var startTime = (i>0) ? times[i-1] : "00:00"; var endTime = (i"+startTime+""; html += ""; //to html += ""; // temp if (widget.TEMPLIST == null) { widget.TEMPLIST = new Array(); for (var k=5; k <= 30; k+=0.5) { widget.TEMPLIST.push(k); } } html += ""; //ADD-Button html += ""; //DEL-Button html += ""; html += ""; } $(table).append(html); $(div).append(table); FW_weekprofileEditRowStyle(table); return div; } function FW_weekprofileEditWeek(widget) { $(widget.MENU.CONTENT).empty(); var table = widget.CONTENT; var daysInRow = 2; if (widget.EDIT_DAYSINROW) daysInRow = widget.EDIT_DAYSINROW; $(table).append(''); var tr = $(table).find("tr:last"); for (var i = 0; i < shortDays.length; ++i) { tr.append('').insertAfter(tr); tr = $(table).find("tr:last"); } } tr.append("
-
'); tr.find('td:last').append(FW_weekprofileEditDay(widget,i)); if ((i+1)%daysInRow == 0){ $('
"); tr = tr.find("tr:last"); tr.append("
"); tr.append(""); } function FW_weekprofileSendCallback(devName, data) { var widget = $('div[informid="'+devName+'"]').get(0); if(!data.match(/^[\r\n]*$/)) // ignore empty answers FW_okDialog('
'+data+'
',widget); } function FW_weekprofilePrepAndSendProf(devName) { var widget = $('div[informid="'+devName+'"]').get(0); var tableDay = $(widget).find("table[id*=\"weekprofile."+devName+"\"]"); if (tableDay.length == 0){ FW_errmsg(widget.DEVICE+" internal error ",10000); return; } var prf=new Object(); for (var i = 0; i < tableDay.length; ++i) { var timeEL = $(tableDay[i]).find('input[name="ENDTIME"]'); var tempEL = $(tableDay[i]).find('select[name="TEMP"]'); if (timeEL.length != tempEL.length){ FW_errmsg(widget.DEVICE+" internal error ",10000); return; } var day = $(tableDay[i]).attr("data-day"); prf[day] = new Object(); prf[day]['time'] = new Array(); prf[day]['temp'] = new Array(); for (var k = 0; k < timeEL.length; ++k) { prf[day]['time'].push(timeEL[k].value); prf[day]['temp'].push(tempEL[k].value); } } try { var data=JSON.stringify(prf); FW_cmd(FW_root+"?cmd=set "+widget.DEVICE+" profile_data "+widget.CURTOPIC+':'+widget.CURPRF+" "+data+"&XHR=1",function(arg) {FW_weekprofileSendCallback(widget.DEVICE,arg);}); } catch(e){ FW_errmsg(devName+" Parameter "+e,5000); return; } for (var i = 0; i < shortDays.length; ++i) { var day = shortDays[i]; if (prf[day] != null){ widget.PROFILE[day] = prf[day]; } } FW_weekprofileBack(widget); } function FW_weekprofileBack(widget) { if (widget.JMPBACK){ var isInIframe = (window.location != window.parent.location) ? true : false; if (isInIframe) { parent.history.back(); } else if (document.referrer) { window.location.assign(document.referrer) } else { window.history.back() //maybe problems with reload } } else { widget.MODE = "SHOW"; widget.setValueFn("REUSEPRF"); } } function FW_weekprofileEditAbort(devName) { var widget = $('div[informid="'+devName+'"]').get(0); FW_weekprofileBack(widget); } function FW_weekprofileGetProfileData(devName,data) { var widget = $('div[informid="'+devName+'"]').get(0); $(widget.CONTENT).empty(); var reuse = (data == "REUSEPRF") ? 1 : 0; var prf={}; try { (reuse) ? prf = widget.PROFILE : prf=JSON.parse(data); } catch(e){ console.log(devName+" error parsing json '" +data+"'"); FW_errmsg(devName+" Parameter "+e,5000); return; } widget.PROFILE = prf; widget.PRFREF = null; if (widget.MODE == 'SHOW') { if (reuse == 0 && widget.USETOPICS != 0) { //check if data is a reference FW_cmd(FW_root+'?cmd=get '+devName+' profile_references '+widget.CURTOPIC+':'+widget.CURPRF+'&XHR=1',function(data){ if (data != 0) { var name = data.split(':'); if (name.length == 2) { widget.PRFREF = data; } else { console.log(devName+" error get references '" +data+"'"); } } FW_weekprofileShow(widget); }); } else { FW_weekprofileShow(widget); } } else if (widget.MODE == 'EDIT') { FW_weekprofileEditWeek(widget); } else { FW_errmsg(devName+" unknown Mode",10000); } } function FW_weekprofileGetValues(devName,what,data) { data = data.trim(); if(data.match(/^[\r\n]*$/)) {return;} var widget = $('div[informid="'+devName+'"]').get(0); if (what == "WEEKDAYS"){ widget.WEEKDAYS = data.split(','); } else if (what == "PROFILENAMES") { widget.PROFILENAMES = data.split(','); if (widget.MODE != 'EDIT') { if (widget.CURPRF == null && widget.PROFILENAMES) { widget.CURPRF = widget.PROFILENAMES[0]; } FW_queryValue('get '+devName+' profile_data '+widget.CURTOPIC+':'+widget.CURPRF+' 1', widget); } else { widget.setValueFn("REUSEPRF"); } } else if (what == "TOPICNAMES") { widget.TOPICNAMES = data.split(','); var found = 0; for (var k = 0; k < widget.TOPICNAMES.length; ++k) { widget.TOPICNAMES[k] = widget.TOPICNAMES[k].trim(); if (widget.CURTOPIC == widget.TOPICNAMES[k]) { found=1; } } if (found==0) { widget.CURTOPIC = widget.TOPICNAMES[0]; } FW_weekprofileChacheTo(devName,widget.CURTOPIC,null); } else if (what == "TRANSLATE") { var arr = data.split(','); widget.TRANSLATIONS = new Array(); for (var k = 0; k < arr.length; ++k) { var trans = arr[k].split(':'); if (trans.length == 2) widget.TRANSLATIONS[trans[0].trim()] = trans[1].trim(); } } else if (what == "TEMPLIST") { console.log(devName+" TEMPLIST '" +data+"'"); var arr = data.split(','); widget.TEMPLIST = new Array(); var i = -1; while (++i < arr.length) { widget.TEMPLIST[i] = arr[i]; } } } function FW_weekprofileCreate(elName, devName, vArr, currVal, set, params, cmd) { // called from FW_replaceWidget fhemweb.js if( 0 ) { console.log( "elName: "+elName ); console.log( "devName: "+devName ); // attr dev console.log( "vArr: "+vArr ); // attr arg split ',' console.log( "currVal: "+currVal ); // attr current console.log( "set: "+set ); // attr cmd split ' ' first entry console.log( "params: "+params ); // attr cmd list split ' ' without first entry console.log( "cmd: "+cmd ); // function for ToDo } if(!vArr.length || vArr[0] != "weekprofile") return undefined; var widget = $('div[informid="'+devName+'"]').get(0); var content = $('').get(0); $(widget).append(content); widget.CONTENT = content; widget.HEADER = $('div[id="weekprofile.'+devName+'.header"]').get(0); widget.MENU = new Object(); widget.MENU.BASE = $(widget.HEADER).find('div[id*="menu.base"]').get(0); var menuContent = ''; $(widget.MENU.BASE.parentElement.parentElement).append(menuContent); widget.MENU.CONTENT = $(widget.HEADER).find('div[id*="menu.content"]').get(0); widget.JMPBACK = null; widget.MODE = 'SHOW'; widget.USETOPICS = 0; widget.TEMPLIST = null; for (var i = 1; i < vArr.length; ++i) { var arg = vArr[i].split(':'); switch (arg[0]) { case "MODE": widget.MODE = arg[1]; break; case "JMPBACK": widget.JMPBACK = arg[1]; break; case "MASTERDEV": widget.MASTERDEV = arg[1]; break; case "USETOPICS": widget.USETOPICS = arg[1]; break; case "DAYINROW": widget.EDIT_DAYSINROW = arg[1]; break; } } widget.DEVICE = devName; widget.WEEKDAYS = shortDays.slice(); var current = currVal.split(':'); widget.CURTOPIC = current[0]; widget.CURPRF = current[1]; widget.setValueFn = function(arg){FW_weekprofileGetProfileData(devName,arg);} widget.activateFn = function(arg){ FW_cmd(FW_root+'?cmd=get '+devName+' tempList&XHR=1',function(data){FW_weekprofileGetValues(devName,"TEMPLIST",data);}); FW_queryValue('get '+devName+' profile_data '+widget.CURTOPIC+':'+widget.CURPRF+' 1', widget); // use keywords FW_cmd(FW_root+'?cmd={AttrVal("'+devName+'","widgetWeekdays","")}&XHR=1',function(data){FW_weekprofileGetValues(devName,"WEEKDAYS",data);}); FW_cmd(FW_root+'?cmd={AttrVal("'+devName+'","widgetTranslations","")}&XHR=1',function(data){FW_weekprofileGetValues(devName,"TRANSLATE",data);}); if (widget.USETOPICS == 1) { FW_cmd(FW_root+'?cmd=get '+devName+' topic_names&XHR=1',function(data){FW_weekprofileGetValues(devName,"TOPICNAMES",data);}); } else { FW_cmd(FW_root+'?cmd=get '+devName+' profile_names '+widget.CURTOPIC+'&XHR=1',function(data){FW_weekprofileGetValues(devName,"PROFILENAMES",data);}); } }; //inform profile_count changed var prfCnt = $('
').get(0); prfCnt.setValueFn = function(arg){ if (widget.MODE == 'EDIT') { // do not update profile data in edit mode return; } FW_cmd(FW_root+'?cmd=get '+devName+' tempList&XHR=1',function(data){FW_weekprofileGetValues(devName,"TEMPLIST",data);}); if (widget.USETOPICS == 1) { FW_cmd(FW_root+'?cmd=get '+devName+' topic_names&XHR=1',function(data){FW_weekprofileGetValues(devName,"TOPICNAMES",data);}); } else { FW_cmd(FW_root+'?cmd=get '+devName+' profile_names '+widget.CURTOPIC+'&XHR=1',function(data){FW_weekprofileGetValues(devName,"PROFILENAMES",data);}); } } $(widget.HEADER).append(prfCnt); return widget; } FW_widgets['weekprofile'] = { createFn:FW_weekprofileCreate, }; /* =pod =begin html =end html =begin html_DE =end html_DE =cut */