"use strict"; var FW_version={}; FW_version["fhemweb.js"] = "$Id$"; var FW_serverGenerated; var FW_jsLog; var FW_serverFirstMsg = (new Date()).getTime()/1000; var FW_serverLastMsg = FW_serverFirstMsg; var FW_isIE = (navigator.appVersion.indexOf("MSIE") > 0); var FW_isiOS = navigator.userAgent.match(/(iPad|iPhone|iPod)/) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1); /* iPad OS 13+ */ var FW_scripts = {}, FW_links = {}; var FW_docReady = false, FW_longpollType, FW_csrfToken, FW_csrfOk=true; var FW_root = "/fhem"; // root var FW_availableJs={}; var FW_urlParams={}; var embedLoadRetry = 100; var FW_os = "unknown"; if(FW_isiOS) { FW_os = "iOS"; } else if(navigator.userAgent.indexOf("Android") >= 0) { FW_os = "android"; } else if(navigator.userAgent.indexOf("OS X") >= 0) { FW_os = "osx"; } else if(navigator.userAgent.indexOf("Windows") >= 0) { FW_os = "windows"; } else if(navigator.userAgent.indexOf("Linux") >= 0) { FW_os = "linux"; } // createFn returns an HTML Element, which may contain // - setValueFn, which is called when data via longpoll arrives // - activateFn, which is called after the HTML element is part of the DOM. var FW_widgets = { select: { createFn:FW_createSelect }, selectnumbers: { createFn:FW_createSelectNumbers, }, slider: { createFn:FW_createSlider }, time: { createFn:FW_createTime }, noArg: { createFn:FW_createNoArg }, multiple: { createFn:FW_createMultiple }, "multiple-strict": { createFn:FW_createMultiple, second:true }, textField: { createFn:FW_createTextField }, textFieldNL: { createFn:FW_createTextField, second:true }, "textField-long": { createFn:FW_createTextField, second:true }, "textFieldNL-long":{ createFn:FW_createTextField, second:true }, bitfield: { createFn:FW_createBitfield }, widgetList: { createFn:FW_createWidgetList }, }; window.onbeforeunload = function(e) { FW_leaving = 1; return undefined; } window.onerror = function(errMsg, url, lineno) { url = url.replace(/.*\//,''); if($("body").attr("data-confirmJSError") != 0) FW_okDialog(url+" line "+lineno+":
"+errMsg); } function FW_replaceWidgets(parent) { parent.find("div.fhemWidget").each(function() { var dev=$(this).attr("dev"); var cmd=$(this).attr("cmd"); var rd=$(this).attr("reading"); var params = cmd.split(" "); var type=$(this).attr("type"); if(type == undefined) type = "set"; FW_replaceWidget(this, dev, $(this).attr("arg").split(","), $(this).attr("current"), rd, params[0], params.slice(1), function(arg) { FW_cmd(FW_root+"?cmd="+type+" "+dev+ (params[0]=="state" ? "":" "+params[0])+" "+arg+"&XHR=1"); }); }); } function FW_jqueryReadyFn() { if(FW_docReady) // loading fhemweb.js twice is hard to debug return; FW_docReady = true; FW_serverGenerated = $("body").attr("generated"); FW_jsLog = $("body").attr("data-jsLog"); FW_longpollType = $("body").attr("longpoll"); var ajs = $("body").attr("data-availableJs"); if(ajs) { ajs = ajs.split(","); for(var i1=0; i1 tbody > tr").each(function(){ // count the td's var cnt = 0, row=this; $(row).find("> td").each(function(){ var cs = $(this).attr("colspan"); cnt += parseInt(cs ? cs : 1); }); if(maxTd < cnt) maxTd = cnt; tdCount.push(cnt); }); $(tbl).find("> tbody> tr").each(function(){ // set the colspan var tdc = tdCount.shift(); $(this).find("> td:last").each(function(){ var cs = $(this).attr("colspan"); $(this).attr("colspan", maxTd-tdc+(cs ? parseInt(cs) : 1)); }); }); }); $("form input.get[type=submit]").click(function(e) { //"get" via XHR to dialog e.preventDefault(); var cmd = "", el=this; $(el).parent().find("input,[name]").each(function() { cmd += (cmd?"&":"")+encodeURIComponent($(this).attr("name"))+ "="+encodeURIComponent($(this).val()); }); FW_cmd(FW_root+"?"+cmd+"&XHR=1&addLinks=1", function(data) { if(!data.match(/^[\r\n]*$/)) {// ignore empty answers var ma = /^([\s\S]*)<\/html>/.exec(data); if(ma) { FW_okDialog(ma[1], el); } else { FW_okDialog('
'+data+'
', el); } } }); }); $("#saveCheck") .css("cursor", "pointer") .click(function(){ var parent = this; FW_cmd(FW_root+"?cmd=save ?&XHR=1", function(data) { FW_okDialog('
'+data+'
',parent); }); }); $("form").each(function(){ // main input special cases var input = $(this).find("input.maininput"); if(!input.length) return; $(this).on("submit", function(e) { var val = $(input).val(); if(val.match(/^\s*ver.*/)) { // version e.preventDefault(); $(input).val(""); return FW_showVersion(val); } else if(val.match(/^\s*shutdown/)) { // shutdown FW_cmd(FW_root+"?XHR=1&cmd="+val); $(input).val(""); return false; } else if(val.match(/^\s*l\s/)) { // l dev var m = val.match(/^\s*l\s+(.*)/); location.href = FW_root+"?detail="+m[1]; e.preventDefault(); return false; } else if(val.match(/^\s*get\s+/)) { // get // make get use xhr instead of reload //return true; FW_cmd(FW_root+"?cmd="+encodeURIComponent(val)+"&XHR=1", function(data){ if( !data.match( /^[\s\S]*<\/html>/ ) ) { data = data.replace( '<', '<' ); data = '
'+data+'
'; } if( location.href.indexOf('?') === -1 ) $('#content').html(data); else FW_okDialog(data); }); e.preventDefault(); $(input).val(""); return false; } return true; }); }); $("table.attributes tr div.dname") // Click on attribute fills input value .each(function(){ $(this) .html(''+$(this).html()+'') .css({cursor:"pointer"}) .click(function(){ var attrName = $(this).text(); var sel = "#sel_attr"+$(this).attr("data-name").replace(/\./g,'_'); if($(sel+" option[value='"+attrName+"']").length == 0) $(sel).append(''); $(sel).val(attrName); FW_detailSelect(sel, true); $(sel).trigger("change").focus(); }); }); $("[name=icon-filter]").on("change keyup paste", function() { clearTimeout($.data(this, 'delayTimer')); var wait = setTimeout(FW_filterIcons, 300); $(this).data('delayTimer', wait); }); $("pre.motd").each(function(){ // add links for passwort setting var txt = $(this).text(); txt = txt.replace(/(configuring|define|attr) .*/g, function(x) { return ""+x+""; }); $(this).html(txt); $(this).find("a").click(function(){ var txt = $(this).text(); var ma = txt.match(/configuring.*device (.*)/); // ?? if(ma) location.href = FW_root+"?detail="+ma[1]; FW_cmd(FW_root+"?cmd="+encodeURIComponent(txt)+"&XHR=1", function(data){ if(txt.indexOf("attr") == 0) $("pre.motd").html(""); if(txt.indexOf("define") == 0) location.href = FW_root+"?detail=allowed"; }); }); }); var sa = location.search.substring(1).split("&"); for(var i = 0; i < sa.length; i++) { var kv = sa[i].split("="); FW_urlParams[kv[0]] = decodeURIComponent(kv[1]); } $("select[id^=sel_attr],select[id^=sel_set],select[id^=sel_get]") .change(function(){ // online help var val = $(this).val(); var m = $(this).attr("name").match(/arg.(set|get|attr)(.*)/); if(!m) return; $("#devSpecHelp").remove(); var sel=this, devName=m[2], selType=m[1]; var group = $(this).parent().find(':selected').parent().attr('label'); FW_displayHelp(devName, sel, selType, val, group); }); FW_smallScreenCommands(); FW_inlineModify(); FW_detLink(); FW_treeMenu(); $("body").attr("data-os", FW_os); // automatic reload for style change if(location.search.indexOf("cmd=style%20select") > 0) { $('a[href*="style set"],a[onclick*="style set"]').each(function(){ var href = $(this).attr("href"); if(!href && (href = $(this).attr("onclick"))) href = href.substr(15,href.length-16); $(this).click(function(e){ e.preventDefault(); FW_cmd(href+"&XHR=1", function(data) { location.reload(true); }); }); }); } } function FW_displayHelp(devName, sel, selType, val, group) { if(group) { if(group.indexOf("userattr") >= 0) return; devName = (group == "framework" ? "commandref" : group); } FW_getHelp(devName, function(data) { // show either the next or the outer li $("#content") .append(""); var wb = $("#content > #workbench"); wb.html(data); var mtype = wb.find("a[id]").attr("id"), aTag; if(!mtype) mtype = wb.find("a[name]").attr("name"); if(devName == "commandref") mtype = ""; if(mtype) { // current syntax: FHEMWEB-attr-webCmd var mv = (""+mtype+"-"+selType+"-"+val).replace(/[^a-z0-9_-]/ig,'_'); aTag = wb.find("a[id="+mv+"]"); if(!$(aTag).length) { // old style #1 syntax: FHEMWEBwebCmd mv = (""+mtype+val).replace(/[^a-z0-9_-]/ig,'_'); aTag = wb.find("a[name="+mv+"]"); } } if(!$(aTag).length) { // old style #2 syntax : webCmd var v = (val).replace(/[^a-z0-9_-]/ig,'_'); aTag = wb.find("a[name="+v+"]"); } if(!$(aTag).length) { // regexp attributes, like backend_.* wb.find("a[id^='"+mtype+"-"+selType+"-'][data-pattern]").each( function() { var dp = $(this).attr("data-pattern"); // if(!$(aTag).length && val.match(dp)) { if(val.match(dp)) { log("Searching for "+val+", found data-pattern "+dp); aTag = this; } }); } if($(aTag).length) { var liTag = $(aTag).next("li"); if(!$(liTag).length) liTag = $(aTag).parent("li"); if(!$(liTag).length) liTag = $(aTag).parent().next("li"); $("#devSpecHelp").remove(); // shown only one if FHEM is slow if($(liTag).length) { $(sel).closest("div[cmd='"+selType+"']") .after('
') $("#devSpecHelp").html($(liTag).html()); $("#devSpecHelp a").each(function(){ // #130694 var href = $(this).attr("href"); if(href && href.indexOf("#") == 0) { $(this).attr("target", "_blank"); $(this).attr("href", addcsrf(FW_root+"/docs/commandref.html"+$(this).attr("href"))); } }); } } wb.remove(); }); } var FW_helpData={}; function FW_getHelp(dev, fn) { if(FW_helpData[dev]) return fn(FW_helpData[dev]); if(dev == "commandref") { var lang = $("body").attr("data-language"); var url = FW_root+"/docs/commandref_frame"+ (lang == "EN" ? "" : "_"+lang)+".html"; $.ajax({ url:url, headers: { "cache-control": "no-cache" }, success: function(data, textStatus, req){ FW_helpData[dev] = data; return fn(data); }, error:function(xhr, status, err) { log("E:"+err+"/"+status); } }); return; } FW_cmd(FW_root+"?cmd=help "+dev+"&XHR=1", function(data) { if(data.match(/^No help found/) && !dev.match(" DE")) // for our german only friends return FW_getHelp(dev+" DE", fn); FW_helpData[dev] = data; return fn(data); }); } function FW_showVersion(val) { FW_cmd(FW_root+"?cmd="+encodeURIComponent(val)+"&XHR=1", function(data){ var list = Object.keys(FW_version); list.sort(); for(var i1=0; i1'+data+''); }); return false; } function FW_filterIcons() { var icons = $('.dist[title]'); icons.show(); var filterText = $('[name=icon-filter]').val(); if (filterText != '') { var re = RegExp(filterText,"i"); icons.filter(function() { return !re.test(this.title); }).hide(); } } function FW_delete(cmd, fCmd) { if($("body").attr("data-hiddenroom").match(/\binput\b/)) return FW_okDialog("Disabled"); if(!fCmd) fCmd = addcsrf(FW_root+"?cmd="+cmd); var cd = $("body").attr("data-confirmDelete"); if(!cd || cd == 0) { location.href = fCmd; return; } var div = $("
"); $(div).html("Do you really want to "+cmd+"?

"+ " Skip this dialog in the future"); $("body").append(div); $(div).dialog({ dialogClass:"no-close", modal:true, width:"auto", closeOnEscape:true, maxWidth:$(window).width()*0.9, maxHeight:$(window).height()*0.9, buttons: [ {text:"Yes", click:function(){ doClose(); location.href = fCmd; }}, {text:"No", click:doClose} ], close: doClose }); function doClose() { var wn = $("body").attr("data-webName"); if($(div).find("input:checked").length) FW_cmd(FW_root+"?cmd=attr "+wn+" confirmDelete 0&XHR=1"); $(this).dialog("close"); $(div).remove(); } } // For all the links starting with delete (deleteattr, etc) function FW_confirmDelete() { var b = $("body"); var cd = $(b).attr("data-confirmDelete"); if(!cd || cd == 0) return; var wn = $(b).attr("data-webName"); $("div#content").find("a").each(function(){ var href = $(this).attr("href"); if(!href) return; var ma = $(this).attr("href").match(/.*cmd[^=]*=(delete[^&]*).*$/); if(!ma || ma.length != 2) return; FW_removeLink(this); $(this).click(function(e){ FW_delete(ma[1], ma[0]); return false; }); }); } function FW_renameDevice(dev) { var div = $("
"); $(div).html('Rename '+dev+ ' to:

'); $("body").append(div); $(div).dialog({ dialogClass:"no-close", modal:true, width:"auto", closeOnEscape:true, maxWidth:$(window).width()*0.9, maxHeight:$(window).height()*0.9, buttons: [ {text:"Rename", click:function(){ var nn = $(div).find("input").val(); if(!nn.match(/^[a-z0-9._]*$/i)) return FW_okDialog("Illegal characters in the new name"); location.href=addcsrf(FW_root+"?cmd=rename "+dev+" "+nn+"&detail="+nn); }}, {text:"Cancel", click:doClose} ], close: doClose }); function doClose() { $(this).dialog("close"); $(div).remove(); } } // Show the webCmd list in a dialog if: smallScreen & hiddenroom=detail & room function FW_smallScreenCommands() { if($("div#menu select").length == 0 || // not SmallScreen $("div#content").attr("room") == undefined || // not room Overview $("div#content div.col1 a").length > 0) // no hiddenroom=detail return; $("div#content div.col1").each(function(){ var tr = $(this).closest("tr"); if($(tr).find("> td").length <= 2) return; $(this).html(""+$(this).html()+""); $(this).find("a").click(function(){ var t = $("
"), row=0; $(tr).find("> td").each(function(){ $(t).append(""); if(row++ == 0) { $(t).find("tr:last").append($(this).find("a").html()); } else { $(this).attr("data-orig", 1); this.orig=$(this).parent(); $(t).find("tr:last").append($(this).detach()); } }); FW_okDialog(t, this, function(){ $("#FW_okDialog [data-orig]").each(function(){ $(this).detach().appendTo(this.orig); }); }); }); }); } if(window.jQuery) { $(document).ready(FW_jqueryReadyFn); } else { // FLOORPLAN compatibility loadScript("pgm2/jquery.min.js", function() { loadScript("pgm2/jquery-ui.min.js", function() { FW_jqueryReadyFn(); }, true); }, true); } // FLOORPLAN compatibility function FW_delayedStart() { setTimeout("FW_longpoll()", 100); } var FW_logStack=[]; function log(txt) { var d = new Date(); var ms = ("000"+(d.getMilliseconds()%1000)); ms = ms.substr(ms.length-3,3); var lTxt = d.toTimeString().substring(0,8)+"."+ms+" "+txt; if(typeof window.console != "undefined") console.log(lTxt); if(FW_jsLog==1 && FW_longpollType == "websocket") { FW_logStack.push(txt); if(FW_pollConn && FW_pollConn.readyState == FW_pollConn.OPEN) { while(FW_logStack.length) { txt = '{Log 1, "jsLog: '+FW_logStack.shift().replace(/"/g, "'")+'"}'; console.log(txt); FW_pollConn.send(txt); } } } } function addcsrf(arg) { if(typeof FW_csrfToken != "undefined") { arg = arg.replace(/&fwcsrf=[^&]*/,''); arg += '&fwcsrf='+encodeURIComponent(FW_csrfToken); } return arg; } function FW_csrfRefresh(callback) { log("FW_csrfRefresh, last was "+(FW_csrfOk ? "ok":"bad")); if(!FW_csrfOk) // avoid endless loop return; $.ajax({ url:location.pathname+"?XHR=1", success: function(data, textStatus, request){ FW_csrfToken = request.getResponseHeader('x-fhem-csrftoken'); FW_csrfOk = false; if(callback) callback(); } }); } var FW_cmdStack=[]; function FW_cmd(arg, callback, rep) { if(arg.length < 120) log("FW_cmd:"+arg); else log("FW_cmd:"+arg.substr(0,120)+"..."); $.ajax({ url:addcsrf(arg)+'&fw_id='+$("body").attr('fw_id'), headers: { "cache-control": "no-cache" }, dataType: "text", method:'POST', success: function(data, textStatus, req){ FW_csrfOk = true; if(callback) callback(req.responseText); else if(req.responseText) FW_errmsg(req.responseText, 5000); var todo = FW_cmdStack.shift(); if(todo) { log("FW_cmd retry #"+todo.rep); FW_cmd(todo.arg, todo.callback, todo.rep); } }, error:function(xhr, status, err) { // iOS 13+ is not queueing requests, have to do it myself. Forum #116962 if(xhr.status == 0 && xhr.readyState == 0 && (!rep || rep < 10)) { FW_cmdStack.push({ arg:arg, callback:callback, rep:(rep?rep+1:1)}); } else if(xhr.status == 400 && typeof FW_csrfToken != "undefined") { FW_csrfToken = ""; FW_csrfRefresh(function(){FW_cmd(arg, callback)}); } else { log("FW_cmd error: "+status+"/"+JSON.stringify(xhr)); } } }); } function FW_errmsg(txt, timeout) { log("ERRMSG:"+txt+"<"); var errmsg = document.getElementById("errmsg"); if(!errmsg) { if(txt == "") return; errmsg = document.createElement('div'); errmsg.setAttribute("id","errmsg"); document.body.appendChild(errmsg); } if(txt == "") { document.body.removeChild(errmsg); return; } errmsg.innerHTML = txt; if(timeout) setTimeout("FW_errmsg('')", timeout); } function FW_okDialog(txt, parent, removeFn) { $("#FW_okDialog").remove(); var div = $("
"); $(div).html(txt); $("body").append(div); var oldPos = $("body").scrollTop(); $(div).dialog({ dialogClass:"no-close", modal:true, width:"auto", closeOnEscape:true, maxWidth:$(window).width()*0.9, maxHeight:$(window).height()*0.9, buttons: [{text:"OK", click:function(){ $(this).dialog("close"); if(removeFn) removeFn(); $(div).remove(); }}] }); FW_replaceWidgets(div); $(div).find("a").each(function(){FW_replaceLink(this);}); //Forum #33766 if(parent) $(div).dialog( "option", "position", { my: "left top", at: "right bottom", of: parent, collision: "flipfit" }); setTimeout(function(){$("body").scrollTop(oldPos);}, 1); // Not ideal. } function FW_menu(evt, el, arr, dis, fn, embedEl) { if(!embedEl) evt.stopPropagation(); if($("#fwmenu").length) { delfwmenu(); return; } var html = ''; $("body").append(html); function delfwmenu() { $("ul#fwmenu").remove(); $('html').unbind('click.fwmenu'); } var wt = $(window).scrollTop(); $("#fwmenu") .menu({ select: function(e,ui) { // changes the scrollTop(); e.stopPropagation(); fn($(e.currentTarget).find("[row]").attr("row")); delfwmenu(); setTimeout(function(){ $(window).scrollTop(wt) }, 1); // Bug in select? } }); var off = $(el).offset(); if(embedEl) { var embOff = $(embedEl).offset(); off.top += embOff.top; off.left += embOff.left; } var dH = $("#fwmenu").height(), dW = $("#fwmenu").width(), wH = $(window).height(), wW = $(window).width(); var ey = off.top+dH+20, ex = off.left+dW; if(ex>wW && ey>wH) { off.top -= dH; off.left -= (dW+16); } else if(ey > wH) { off.top -= dH; off.left += 20; } else if(ex > wW) { off.left -= (dW+16); } else { off.top += 20; } $("#fwmenu").css(off); $('html').bind('click.fwmenu', function() { delfwmenu(); }); } function FW_getLink(el) { var attr = $(el).attr("href"); if(!attr) { attr = $(el).attr("onclick"); // Tablet/smallScreen version if(!attr) return ""; attr = attr.replace(/^location.href='/,''); attr = attr.replace(/'$/,''); } return attr; } function FW_replaceLink(el) { var attr = FW_getLink(el); if(!attr) return; var ma = attr.match(/^(.*\?)(cmd[^=]*=.*)$/); if(ma == null || ma.length == 0 || !ma[2].match(/=(save|set)/)) { ma = attr.match(new RegExp("^"+FW_root)); // Avoid "Connection lost" @iOS if(ma) { $(el).click(function(e) { // Open link in window/tab, Forum #39154 if(e.shiftKey || e.ctrlKey || e.metaKey || e.button == 1) return; e.preventDefault(); FW_leaving = 1; if($(el).attr("target") == "_blank") { window.open(attr, '_blank').focus(); } else { location.href = attr; } }); } return; } $(el).removeAttr("href"); $(el).removeAttr("onclick"); $(el).click(function() { attr = attr.replace(/&.*$/,''); // remove unnecessary params, forum: #97351 FW_cmd(attr+"&XHR=1", function(txt){ if(!txt) return; if(ma[2].match(/=set/)) // Forum #38875 FW_okDialog('
'+txt+'
', el);
      else
        FW_errmsg(txt, 5000);
    });
  });
  $(el).css("cursor", "pointer");
}

function
FW_htmlQuote(text)
{
  return text.replace(/&/g, '&')    // Same as in 01_FHEMWEB
             .replace(//g, '>');
}

function
FW_inlineModify()       // Do not generate a new HTML page upon pressing modify
{
  var cm;

  if( typeof AddCodeMirror == 'function' ) {
    // init codemirror for FW_style edit textarea
    AddCodeMirror($('textarea[name="data"]'));
  }

  $('#DEFa').click(function(){
    var old = $('#edit').css('display');
    $('#edit').css('display', old=='none' ? 'block' : 'none');
    $('#disp').css('display', old=='none' ? 'none' : 'block');
    if( typeof AddCodeMirror == 'function' ) {
      var s=document.getElementById("edit").getElementsByTagName("textarea");
      AddCodeMirror(s[0], function(pcm) {cm = pcm;});
    }
    });

  var hr = $("body").attr("data-hiddenroom");
  if(!hr || !hr.match(/\binput\b/)) {
    $("table.internals div.dname").each(function(){
      if($(this).text() == "NAME") {
        var dev = $(this).attr("data-name");
        var a=$("NAME");
        $(this).html(a);
        a.click(function(){ FW_renameDevice(dev) });
      }
    });
  }
    
  // Set and attr 
  $("div input.psc[type=submit]:not(.get)").click(function(e){
    e.preventDefault();
    var frm = $(this).closest("form");
    var newDef = typeof cm !== 'undefined' ?
                 cm.getValue() : frm.find("textarea").val();
    var cmd = $(this).attr("name")+"="+$(this).attr("value")+" "+newDef;
    var isDef = true, reloadIfOk = false;

    if(newDef == undefined || $(this).attr("value").indexOf("modify") != 0) {
      isDef = false;
      var div = $(this).closest("div.makeSelect");
      var devName = $(div).attr("dev"),
          cmd = $(div).attr("cmd");
      var sel = frm.find("select");
      var arg = $(sel).val();
      var ifid = (devName+"-"+arg).replace(/([^_a-z0-9])/gi,
                                   function(m){ return "\\"+m });
      if($(".dval[informid="+ifid+"]").length == 0) {// No reading with this name
        if(cmd == "attr" || (cmd == "set" && arg == "attrTemplate")) {
          reloadIfOk = true;
        } else {
          $(this).unbind('click').click();// No element found to replace, reload
          return;
        }
      }
      // Make it similar to submit: values joined by ,
      var nd=frm.find("[name^=val]").map(function(){return $(this).val()}).get();
      newDef = nd.length ? nd.join(",") : frm.find("input:text").val();
      cmd = $(this).attr("name")+"="+cmd+" "+devName+" "+arg+" "+newDef;
    }
    FW_cmd(FW_root+"?"+encodeURIComponent(cmd)+"&XHR=1", function(resp){
      if(!resp && reloadIfOk) {
        var hr = location.href+"";
        location.href = hr+     // retain fw_id
              (hr.match(/fw_id=\d+/) ? "" : '&fw_id='+$("body").attr('fw_id'));

      }
      if(resp) {
        if(!resp.match(/^[\s\S]*<\/html>/ ) ) {
          resp = FW_htmlQuote(resp);
          if(resp.indexOf("\n") >= 0)
            resp = '
'+resp+'
'; } return FW_okDialog(resp); } if(isDef) { newDef = FW_htmlQuote(newDef); if(newDef.indexOf("\n") >= 0) newDef = '
'+newDef+'
'; $("div#disp").html(newDef).css("display", ""); $("div#edit").css("display", "none"); } }); }); } function FW_removeLink(el) { $(el).unbind("click"); $(el).attr("href", "#"); // Desktop: show underlined Text $(el).removeAttr("onclick"); // smallscreen style } // Fill the "detLink" line with life function FW_detLink() { if(FW_isiOS || FW_os == "osx") { // our copy fails here $("#detLink a[href*=forumCopy]").parent().remove(); $("#detLink option[data-cmd^=forumCopy]").remove(); } $("#detLink a").each(function(){ var m = FW_getLink(this).match(/cmd=([^&]*)/); if(!m) // delete is already processed return; FW_removeLink(this); $(this).click(function(){doDetCmd(m[1])}); }); $("#detLink select#moreCmds").change(function(){ doDetCmd($(this).find("option:selected").attr("data-cmd")); }); function doDetCmd(fCmd) { if(!fCmd) return; var m = fCmd.match(/^([^ ]+) (.*)$/); if(!m) return; var cmd=m[1], dev=m[2]; if(cmd == "devSpecHelp") { if($("#devSpecHelp").length) { $("#devSpecHelp").remove(); return; } FW_getHelp(dev, function(data){ $("#content").append('
'); $("#devSpecHelp").html(data); var off = $("#devSpecHelp").position().top-20; $('body, html').animate({scrollTop:off}, 500); }); } else if(cmd == "forumCopy") { FW_cmd(FW_root+"?cmd=list -r -i "+dev+"&XHR=1", function(data) { var ta = document.createElement("textarea"), at=""; if(data.length > 50*1000) { data = data.substr(0,50*1000)+ "\n# ... truncated to 50k, original length "+data.length; at = "

Text truncated to 50k due to forum restrictions."; } ta.value = '[code]'+data+'[/code]'; document.body.appendChild(ta); ta.select(); if(document.execCommand('copy')) FW_okDialog('"forum ready" definition copied to the clipboard.'+at); else FW_okDialog('Could not copy'); document.body.removeChild(ta); }); } else if(cmd == "delete") { FW_delete("delete "+dev); } else if(cmd == "rawDef") { if($("#rawDef").length) { $("#rawDef").remove(); return; } var textAreaStyle = typeof AddCodeMirror == 'function'?'opacity:0':''; $("#content").append('
'+ '